/**
* 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;
import java.util.ArrayList;
import java.util.List;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.core.CloudSimTags;
import org.cloudbus.cloudsim.core.SimEntity;
import org.cloudbus.cloudsim.core.SimEvent;
import org.workflowsim.clustering.BasicClustering;
import org.workflowsim.clustering.BlockClustering;
import org.workflowsim.clustering.HorizontalClustering;
import org.workflowsim.clustering.VerticalClustering;
import org.workflowsim.clustering.balancing.BalancedClustering;
import org.workflowsim.utils.ClusteringParameters;
import org.workflowsim.utils.Parameters;
import org.workflowsim.utils.Parameters.ClassType;
import org.workflowsim.utils.ReplicaCatalog;
/**
* ClusteringEngine is an optional component of WorkflowSim and it merges tasks
* into jobs
*
* @author Weiwei Chen
* @since WorkflowSim Toolkit 1.0
* @date Apr 9, 2013
*
*/
public final class ClusteringEngine extends SimEntity {
/**
* The task list
*/
protected List< Task> taskList;
/**
* The job list
*/
protected List<Job> jobList;
/**
* The task submitted list.
*/
protected List<? extends Task> taskSubmittedList;
/**
* The task received list.
*/
protected List<? extends Task> taskReceivedList;
/**
* The number of tasks submitted.
*/
protected int cloudletsSubmitted;
/**
* The clustering engine to use
*/
protected BasicClustering engine;
/**
* The WorkflowEngineId of the WorkflowEngine
*/
private final int workflowEngineId;
/**
* The WorkflowEngine used in this ClusteringEngine
*/
private final WorkflowEngine workflowEngine;
/**
* Created a new ClusteringEngine object.
*
* @param name name to be associated with this entity (as required by
* Sim_entity class from simjava package)
* @param schedulers the number of schedulers in this ClusteringEngine
* @throws Exception the exception
* @pre name != null
* @post $none
*/
public ClusteringEngine(String name, int schedulers) throws Exception {
super(name);
setJobList(new ArrayList<>());
setTaskList(new ArrayList<>());
setTaskSubmittedList(new ArrayList<>());
setTaskReceivedList(new ArrayList<>());
cloudletsSubmitted = 0;
this.workflowEngine = new WorkflowEngine(name + "_Engine_0", schedulers);
this.workflowEngineId = this.workflowEngine.getId();
}
/**
* returns the WorkflowEngineId
*
* @return workflow engine id
*/
public int getWorkflowEngineId() {
return this.workflowEngineId;
}
/**
* returns the WorkflowEngine
*
* @return workflow engine
*/
public WorkflowEngine getWorkflowEngine() {
return this.workflowEngine;
}
/**
* This method is used to send to the broker the list of cloudlets.
*
* @param list the list
* @pre list !=null
* @post $none
*/
public void submitTaskList(List<Task> list) {
getTaskList().addAll(list);
}
/**
* Processes events available for this ClusteringEngine.
*
* @pre ev != null
* @post $none
*/
protected void processClustering() {
/**
* The parameters from configuration file
*/
ClusteringParameters params = Parameters.getClusteringParameters();
switch (params.getClusteringMethod()) {
/**
* Perform Horizontal Clustering
*/
case HORIZONTAL:
// if clusters.num is set in configuration file
if (params.getClustersNum() != 0) {
this.engine = new HorizontalClustering(params.getClustersNum(), 0);
} // if clusters.size is set in configuration file
else if (params.getClustersSize() != 0) {
this.engine = new HorizontalClustering(0, params.getClustersSize());
}
break;
/**
* Perform Vertical Clustering
*/
case VERTICAL:
int depth = 1;
this.engine = new VerticalClustering(depth);
break;
/**
* Perform Block Clustering
*/
case BLOCK:
this.engine = new BlockClustering(params.getClustersNum(), params.getClustersSize());
break;
/**
* Perform Balanced Clustering
*/
case BALANCED:
this.engine = new BalancedClustering(params.getClustersNum());
break;
/**
* By default, it does no clustering
*/
default:
this.engine = new BasicClustering();
break;
}
engine.setTaskList(getTaskList());
engine.run();
setJobList(engine.getJobList());
}
/**
* Adds data stage-in jobs to the job list
*/
protected void processDatastaging() {
/**
* All the files of this workflow, it is saved in the workflow engine
*/
List<FileItem> list = this.engine.getTaskFiles();
/**
* A bug of cloudsim, you cannot set the length of a cloudlet to be
* smaller than 110 otherwise it will fail The reason why we set the id
* of this job to be getJobList().size() is so that the job id is the
* next available id
*/
Job job = new Job(getJobList().size(), 110);
/**
* This is a very simple implementation of stage-in job, in which we Add
* all the files to be the input of this stage-in job so that
* WorkflowSim will transfers them when this job is executed
*/
List<FileItem> fileList = new ArrayList<>();
for (FileItem file : list) {
/**
* To avoid duplicate files
*/
if (file.isRealInputFile(list)) {
ReplicaCatalog.addFileToStorage(file.getName(), Parameters.SOURCE);
fileList.add(file);
}
}
job.setFileList(fileList);
job.setClassType(ClassType.STAGE_IN.value);
/**
* stage-in is always first level job
*/
job.setDepth(0);
job.setPriority(0);
/**
* A very simple strategy if you have multiple schedulers and
* sub-workflows just use the first scheduler
*/
job.setUserId(getWorkflowEngine().getSchedulerId(0));
/**
* add stage-in job
*/
for (Job cJob : getJobList()) {
/**
* first level jobs
*/
if (cJob.getParentList().isEmpty()) {
cJob.addParent(job);
job.addChild(cJob);
}
}
getJobList().add(job);
}
/**
* Processes events available for this Broker.
*
* @param ev a SimEvent object
* @pre ev != null
* @post $none
*/
@Override
public void processEvent(SimEvent ev) {
switch (ev.getTag()) {
case WorkflowSimTags.START_SIMULATION:
break;
case WorkflowSimTags.JOB_SUBMIT:
List list = (List) ev.getData();
setTaskList(list);
/**
* It doesn't mean we must do clustering here because by default
* the processClustering() does nothing unless in the
* configuration file we have specified to use clustering
*/
processClustering();
/**
* Add stage-in jobs Currently we just add a job that has
* minimum runtime but inputs all input data at the beginning of
* the workflow execution
*/
processDatastaging();
sendNow(this.workflowEngineId, WorkflowSimTags.JOB_SUBMIT, getJobList());
break;
case CloudSimTags.END_OF_SIMULATION:
shutdownEntity();
break;
default:
processOtherEvent(ev);
break;
}
}
/**
* 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.");
}
/**
* Send an internal event communicating the end of the simulation.
*
* @pre $none
* @post $none
*/
protected 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, WorkflowSimTags.START_SIMULATION);
}
/**
* Gets the task list.
*
* @return the task list
*/
@SuppressWarnings("unchecked")
public List<Task> getTaskList() {
return (List<Task>) taskList;
}
/**
* Gets the job list.
*
* @return the job list
*/
public List<Job> getJobList() {
return jobList;
}
/**
* Sets the task list.
*
* @param taskList the new task list
*/
protected void setTaskList(List<Task> taskList) {
this.taskList = taskList;
}
/**
* Sets the job list.
*
* @param jobList the new job list
*/
protected void setJobList(List<Job> jobList) {
this.jobList = jobList;
}
/**
* Gets the tasks submitted list.
*
* @return the task submitted list
*/
@SuppressWarnings("unchecked")
public List<Task> getTaskSubmittedList() {
return (List<Task>) taskSubmittedList;
}
/**
* Sets the tasks submitted list.
*
* @param taskSubmittedList the new task submitted list
*/
protected void setTaskSubmittedList(List<Task> taskSubmittedList) {
this.taskSubmittedList = taskSubmittedList;
}
/**
* Gets the task received list.
*
* @return the task received list
*/
@SuppressWarnings("unchecked")
public List<Task> getTaskReceivedList() {
return (List<Task>) taskReceivedList;
}
/**
* Sets the task received list.
*
* @param taskReceivedList the new cloudlet received list
*/
protected void setTaskReceivedList(List<Task> taskReceivedList) {
this.taskReceivedList = taskReceivedList;
}
}