/*
* Copyright (c) 2010-2012 Thiago T. Sá
*
* This file is part of CloudReports.
*
* CloudReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CloudReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For more information about your rights as a user of CloudReports,
* refer to the LICENSE file or see <http://www.gnu.org/licenses/>.
*/
package cloudreports.reports;
import cloudreports.business.SettingBusiness;
import cloudreports.dao.MigrationDAO;
import cloudreports.dao.ReportDataDAO;
import cloudreports.dao.SettingDAO;
import cloudreports.database.Database;
import cloudreports.extensions.PowerDatacenter;
import cloudreports.models.DatacenterRegistry;
import cloudreports.models.Migration;
import cloudreports.models.ReportData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.cloudbus.cloudsim.DatacenterBroker;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.power.PowerHost;
/**
* Provides methods to collect simulation data.
*
* @author Thiago T. Sá
* @since 1.0
*/
public class DataCollector {
/** The label used for the bandwidth resources. */
private static final String BANDWIDTH = "BANDWIDTH";
/** The label used for the CPU resources. */
private static final String CPU = "CPU";
/** The label used for the power resources. */
private static final String POWER = "POWER";
/** The label used for the RAM resources. */
private static final String RAM = "RAM";
/** The number of samples to be considered when dealing with monitored
* resources.
*/
private static final int SAMPLES = 2;
/** A list of transient report data. */
private List<ReportData> dataList;
/** A map of datacenters. */
private HashMap<String,PowerDatacenter> datacenters;
/** A map of brokers. */
private HashMap<String,DatacenterBroker> brokers;
/** A list of monitored resources. */
private List<ReportData> monitoredUsedResources;
/** The last moment data was collected. */
private double lastClock;
/**
* Creates an instance of a data collector.
*
* @param datacenters a map of datacenters to keep track of.
* @param brokers a map of brokers to keep track of.
* @since 1.0
*/
public DataCollector(HashMap<String,PowerDatacenter> datacenters, HashMap<String,DatacenterBroker> brokers) {
Database.cleanTempReport();
this.datacenters = datacenters;
this.brokers = brokers;
this.monitoredUsedResources = new ArrayList<ReportData>();
this.dataList = new ArrayList<ReportData>();
insertClearedData(0);
}
/**
* Gets the last moment data was collected.
*
* @return the last moment data was collected.
*/
public double getLastClock() {
return lastClock;
}
/**
* Collects data from virtual machines and hosts and adds them to a
* transient list.
* If the transient list's size gets greater than 1000, the data is flushed
* to the database.
*
* @see #flushData()
* @since 1.0
*/
public void collectData() {
collectVmsData();
collectHostsData();
if(dataList.size() > 10000) {
flushData();
}
}
/**
* Collects data from virtual machines and adds them to a transient list.
*
* @since 1.0
*/
private void collectVmsData() {
List<String> brokerNames = Arrays.asList(brokers.keySet().toArray(new String[0]));
double currentTime = CloudSim.clock();
this.lastClock = currentTime;
for(String brokerName : brokerNames) {
DatacenterBroker broker = brokers.get(brokerName);
double overallRam = 0,
overallCpu = 0,
overallBandwidth = 0;
int currentSimulation = SettingBusiness.getCurrentSimulation();
List<Vm> vmsList = broker.getVmList();
for(Vm vm : vmsList) {
int vmId = vm.getId();
double ramUtilization = (vm.getCurrentAllocatedRam()/vm.getRam())*100;
dataList.add(new ReportData(RAM, null, brokerName, null, vmId, currentTime, ramUtilization, currentSimulation));
overallRam += ramUtilization;
double cpuUtilization = (vm.getCurrentRequestedTotalMips()/vm.getMips())*100;
dataList.add(new ReportData(CPU, null, brokerName, null, vmId, currentTime, cpuUtilization, currentSimulation));
overallCpu += cpuUtilization;
double bwUtilization = (vm.getCurrentAllocatedBw()/vm.getBw())*100;
dataList.add(new ReportData(BANDWIDTH, null, brokerName, null, vmId, currentTime, bwUtilization, currentSimulation));
overallBandwidth += bwUtilization;
}
int numOfVms = vmsList.size();
dataList.add(new ReportData(RAM, null, brokerName, currentTime, overallRam/numOfVms, currentSimulation));
dataList.add(new ReportData(CPU, null, brokerName, currentTime, overallCpu/numOfVms, currentSimulation));
dataList.add(new ReportData(BANDWIDTH, null, brokerName, currentTime, overallBandwidth/numOfVms, currentSimulation));
}
}
/**
* Collects data from hosts and adds them to a transient list.
*
* @since 1.0
*/
private void collectHostsData() {
List<String> datacenterNames = Arrays.asList(datacenters.keySet().toArray(new String[0]));
double currentTime = CloudSim.clock();
this.lastClock = currentTime;
for(String datacenterName : datacenterNames) {
PowerDatacenter datacenter = datacenters.get(datacenterName);
double overallRam = 0,
overallCpu = 0,
overallBandwidth = 0,
overallPower = 0;
int currentSimulation = SettingBusiness.getCurrentSimulation();
List<PowerHost> hostsList = datacenter.getHostList();
for(PowerHost host : hostsList) {
int hostId = host.getId();
double ramUtilization = (host.getUtilizationOfRam()/host.getRam())*100;
dataList.add(new ReportData(RAM, datacenterName, null, hostId, null, currentTime, ramUtilization, currentSimulation));
overallRam += ramUtilization;
double cpuUtilization = (host.getUtilizationOfCpuMips()/host.getTotalMips())*100;
dataList.add(new ReportData(CPU, datacenterName, null, hostId, null, currentTime, cpuUtilization, currentSimulation));
overallCpu += cpuUtilization;
double bwUtilization = (host.getUtilizationOfBw()/host.getBw())*100;
dataList.add(new ReportData(BANDWIDTH, datacenterName, null, hostId, null, currentTime, bwUtilization, currentSimulation));
overallBandwidth += bwUtilization;
double powerUtilization = (host.getPower()/host.getMaxPower())*100;
dataList.add(new ReportData(POWER, datacenterName, null, hostId, null, currentTime, powerUtilization, currentSimulation));
overallPower += powerUtilization;
}
int numOfHosts = hostsList.size();
dataList.add(new ReportData(RAM, datacenterName, null, currentTime, overallRam/numOfHosts, currentSimulation));
dataList.add(new ReportData(CPU, datacenterName, null, currentTime, overallCpu/numOfHosts, currentSimulation));
dataList.add(new ReportData(BANDWIDTH, datacenterName, null, currentTime, overallBandwidth/numOfHosts, currentSimulation));
dataList.add(new ReportData(POWER, datacenterName, null, currentTime, overallPower/numOfHosts, currentSimulation));
}
}
/**
* Inserts cleared data into a report.
*
* @param time the simulation time at which the cleared data must be
* inserted.
* @since 1.0
*/
public void insertClearedData(double time) {
//Create cleared data for virtual machines
List<String> brokerNames = Arrays.asList(brokers.keySet().toArray(new String[0]));
ReportDataDAO rdDAO = new ReportDataDAO();
double currentTime = time;
int currentSimulation = SettingBusiness.getCurrentSimulation();
for (String brokerName : brokerNames) {
DatacenterBroker broker = brokers.get(brokerName);
List<Vm> vmsList = broker.getVmList();
for (Vm vm : vmsList) {
int vmId = vm.getId();
rdDAO.insertVmData(RAM, brokerName, vmId, currentTime, 0, currentSimulation);
rdDAO.insertVmData(CPU, brokerName, vmId, currentTime, 0, currentSimulation);
rdDAO.insertVmData(BANDWIDTH, brokerName, vmId, currentTime, 0, currentSimulation);
}
rdDAO.insertCustomerOverallData(RAM, brokerName, currentTime, 0, currentSimulation);
rdDAO.insertCustomerOverallData(CPU, brokerName, currentTime, 0, currentSimulation);
rdDAO.insertCustomerOverallData(BANDWIDTH, brokerName, currentTime, 0, currentSimulation);
}
//Create cleared data for hosts
List<String> datacenterNames = Arrays.asList(datacenters.keySet().toArray(new String[0]));
for (String datacenterName : datacenterNames) {
PowerDatacenter datacenter = datacenters.get(datacenterName);
List<PowerHost> hostsList = datacenter.getHostList();
for (PowerHost host : hostsList) {
int hostId = host.getId();
rdDAO.insertHostData(RAM, datacenterName, hostId, currentTime, 0, currentSimulation);
rdDAO.insertHostData(CPU, datacenterName, hostId, currentTime, 0, currentSimulation);
rdDAO.insertHostData(BANDWIDTH, datacenterName, hostId, currentTime, 0, currentSimulation);
rdDAO.insertHostData(POWER, datacenterName, hostId, currentTime, 0, currentSimulation);
}
rdDAO.insertDatacenterOverallData(RAM, datacenterName, currentTime, 0, currentSimulation);
rdDAO.insertDatacenterOverallData(CPU, datacenterName, currentTime, 0, currentSimulation);
rdDAO.insertDatacenterOverallData(BANDWIDTH, datacenterName, currentTime, 0, currentSimulation);
rdDAO.insertDatacenterOverallData(POWER, datacenterName, currentTime, 0, currentSimulation);
}
}
/**
* Inserts migration data into the database.
*
* @param migrationList the list of migration data to be inserted.
* @since 1.0
*/
public void flushMigrations(List<Migration> migrationList) {
MigrationDAO mDAO = new MigrationDAO();
mDAO.insertMigrations(migrationList);
}
/**
* Inserts report data from {@link #dataList} into the database.
*
* @since 1.0
*/
public void flushData() {
if(!this.dataList.isEmpty()) {
ReportDataDAO rDAO = new ReportDataDAO();
rDAO.insertDataList(dataList);
dataList.clear();
}
}
/**
* Collects monitored resources.
*
* @see DatacenterRegistry#monitoringInterval
* @since 1.0
*/
public void collectMonitoredUsedResources() {
List<String> datacenterNames = Arrays.asList(datacenters.keySet().toArray(new String[0]));
double currentTime = CloudSim.clock();
for (String datacenterName : datacenterNames) {
PowerDatacenter datacenter = datacenters.get(datacenterName);
List<PowerHost> hostsList = datacenter.getHostList();
for (PowerHost host : hostsList) {
int hostId = host.getId();
double ramUtilization = (host.getUtilizationOfRam() / host.getRam()) * 100;
insertMonitoredUsedResources(new ReportData(RAM, datacenterName, null, hostId, null, currentTime, ramUtilization, 0));
double cpuUtilization = (host.getUtilizationOfCpuMips() / host.getTotalMips()) * 100;
insertMonitoredUsedResources(new ReportData(CPU, datacenterName, null, hostId, null, currentTime, cpuUtilization, 0));
}
}
}
/**
* Inserts monitored data into {@link #monitoredUsedResources}.
*
* @param data the data to be inserted.
* @since 1.0
*/
private void insertMonitoredUsedResources(ReportData data) {
List<ReportData> sampleList = new ArrayList<ReportData>();
for(ReportData sample : this.monitoredUsedResources) {
if(sample.getDatacenterName().equals(data.getDatacenterName()) &&
sample.getHostId().equals(data.getHostId()) &&
sample.getType().equals(data.getType())) {
sampleList.add(sample);
}
}
if(sampleList.size() >= SAMPLES) {
ReportData olderSample = sampleList.get(0);
for(ReportData sample : sampleList) {
if(sample.getTime() < olderSample.getTime()) {
olderSample = sample;
}
}
this.monitoredUsedResources.remove(olderSample);
}
this.monitoredUsedResources.add(data);
}
/**
* Gets a list of monitored resources.
*
* @param datacenterName the name of the monitored datacenter.
* @param hostId the id of the monitored host.
* @param type the type of the monitored resource.
* @since 1.0
*/
public List<Double> getMonitoredUsedResources(String datacenterName, int hostId, String type) {
List<Double> valuesList = new ArrayList<Double>();
for (ReportData sample : this.monitoredUsedResources) {
if (sample.getDatacenterName().equals(datacenterName)
&& sample.getHostId().equals(hostId)
&& sample.getType().equals(type)) {
valuesList.add(sample.getAmount());
}
}
return valuesList;
}
}