/**
* Copyright 2012-2013 University Of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.workflowsim.planning;
import java.util.ArrayList;
import java.util.List;
import org.cloudbus.cloudsim.Vm;
import org.workflowsim.FileItem;
import org.workflowsim.Task;
import org.workflowsim.utils.Parameters;
/**
* The Distributed HEFT planning algorithm. The difference compared to HEFT:
*
* 1. We are able to specify the bandwidth between each pair of vms in the
* bandwidths of Parameters.
* 2. Instead of using the average communication cost in HEFT, we also aim to
* optimize the communication cost
*
* @author Weiwei Chen
* @since WorkflowSim Toolkit 1.0
* @date Nov 10, 2013
*/
public class DHEFTPlanningAlgorithm extends BasePlanningAlgorithm {
/**
* The main function
*/
@Override
public void run() {
List<Vm> vmList = getVmList();
double [][] bandwidths = new double[vmList.size()][vmList.size()];
for(int i = 0; i < vmList.size(); i++){
for(int j = i ; j < vmList.size(); j++){
bandwidths[i][j] = bandwidths [j][i] = Math.min(vmList.get(i).getBw(), vmList.get(j).getBw());
}
}
for (Object vmObject : getVmList()) {
Vm vm = (Vm)vmObject;
vm.getBw();
}
int vmNum = getVmList().size();
int taskNum = getTaskList().size();
double [] availableTime = new double[vmNum];
//cloudlet id starts from 1
double [][] earliestStartTime = new double[taskNum + 1][vmNum];
double [][] earliestFinishTime = new double[taskNum + 1][vmNum];
int [] allocation = new int[taskNum + 1];
List<Task> taskList = new ArrayList(getTaskList());
List<Task> readyList = new ArrayList<>();
while(!taskList.isEmpty()){
readyList.clear();
for(Task task : taskList){
boolean ready = true;
for(Task parent: task.getParentList()){
if(taskList.contains(parent)){
ready = false;
break;
}
}
if(ready){
readyList.add(task);
}
}
taskList.removeAll(readyList);
//schedule readylist
for(Task task: readyList){
long [] fileSizes = new long[task.getParentList().size()];
int parentIndex = 0;
for(Task parent: task.getParentList()){
long fileSize = 0;
for(FileItem file : task.getFileList()){
if(file.getType()==Parameters.FileType.INPUT){
for(FileItem file2 : parent.getFileList()){
if(file2.getType() == Parameters.FileType.OUTPUT && file2.getName().equals(file.getName()))
{
fileSize += file.getSize();
}
}
}
}
fileSizes[parentIndex] = fileSize;
parentIndex ++;
}
double minTime = Double.MAX_VALUE;
int minTimeIndex = 0;
for(int vmIndex = 0; vmIndex < getVmList().size(); vmIndex++){
Vm vm = (Vm)getVmList().get(vmIndex);
double startTime = availableTime[vm.getId()];
parentIndex = 0;
for(Task parent: task.getParentList()){
int allocatedVmId = allocation[parent.getCloudletId()];
double actualFinishTime = earliestFinishTime[parent.getCloudletId()][allocatedVmId];
double communicationTime = fileSizes[parentIndex] / bandwidths[allocatedVmId][vm.getId()];
if(actualFinishTime + communicationTime > startTime){
startTime = actualFinishTime + communicationTime;
}
parentIndex ++;
}
earliestStartTime[task.getCloudletId()][vm.getId()] = startTime;
double runtime = task.getCloudletLength() / vm.getMips();
earliestFinishTime[task.getCloudletId()][vm.getId()] = runtime + startTime;
if(runtime + startTime < minTime){
minTime = runtime + startTime;
minTimeIndex = vmIndex;
}
}
allocation[task.getCloudletId()] = minTimeIndex;//we do not really need it use task.getVmId
task.setVmId(minTimeIndex);
availableTime[minTimeIndex] = minTime;
}
}
}
}