/**
* 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.clustering;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.workflowsim.Task;
import org.workflowsim.utils.Parameters;
/**
* VerticalClustering merges tasks at the same pipeline
*
* @author Weiwei Chen
* @since WorkflowSim Toolkit 1.0
* @date Apr 9, 2013
*/
public class VerticalClustering extends BasicClustering {
/* The maximum depth to explore. */
private final int mDepth;
/* The checkpoint map. */
private final Map<Integer, Boolean> mHasChecked;
/**
* Initialize a VeriticalClustering object
*
* @param depth depth
*/
public VerticalClustering(int depth) {
super();
this.mDepth = depth;
this.mHasChecked = new HashMap<>();
}
/**
* Sets the checkpoint of a task
*
* @param index id of a task
*/
private void setCheck(int index) {
if (mHasChecked.containsKey(index)) {
mHasChecked.remove(index);
}
mHasChecked.put(index, true);
}
/**
* Gets the checkpoint of a task
*
* @param index id of a task
* @return
*/
private boolean getCheck(int index) {
if (mHasChecked.containsKey(index)) {
return mHasChecked.get(index);
}
return false;
}
/**
* The main function
*/
@Override
public void run() {
if (mDepth > 0) {
/**
* Specially for Montage workflow since it has duplicate edges
*/
if (Parameters.getReduceMethod().equals("montage")) {
removeDuplicateMontage();
}
Task root = super.addRoot();
Task node;
List<Task> taskList = new ArrayList<>();
Stack<Task> stack = new Stack<>();
stack.push(root);
while (!stack.empty()) {
node = (Task) stack.pop();
if (!getCheck(node.getCloudletId())) {
setCheck(node.getCloudletId());
int pNum = node.getParentList().size();
int cNum = node.getChildList().size();
for (Task cNode : node.getChildList()) {
stack.push(cNode);
}
if (pNum == 0) {
//root skip it
} else if (pNum > 1) {
if (cNum > 1 || cNum == 0) {
if (!taskList.isEmpty()) {
addTasks2Job(taskList);
taskList.clear();
}
taskList.add(node);
addTasks2Job(taskList);
taskList.clear();
} else {//cNum==1
//cut and add new
if (!taskList.isEmpty()) {
addTasks2Job(taskList);
taskList.clear();
}
if (!taskList.contains(node)) {
taskList.add(node);
}
}
} else {//pNum == 1
if (cNum > 1 || cNum == 0) {
//This is different to the case of pNum > 1
taskList.add(node);
addTasks2Job(taskList);
taskList.clear();
} else {
//This is also different to the case of pNum > 1
if (!taskList.contains(node)) {
taskList.add(node);
}
}
}
} else {
if (!taskList.isEmpty()) {
addTasks2Job(taskList);
taskList.clear();
}
}
}
}
mHasChecked.clear();
super.clean();
updateDependencies();
addClustDelay();
}
/**
* Remove duplicate just for Montage Set in reducer.method
*/
public void removeDuplicateMontage() {
List jobList = this.getTaskList();
for (Object jobList1 : jobList) {
Task node = (Task) jobList1;
String name = node.getType();
switch (name) {
case "mBackground":
//remove all of its parents of mProjectPP
for (int j = 0; j < node.getParentList().size(); j++) {
Task parent = (Task) node.getParentList().get(j);
if (parent.getType().equals("mProjectPP")) {
j--;
node.getParentList().remove(parent);
parent.getChildList().remove(node);
}
} break;
case "mAdd":
for (int j = 0; j < node.getParentList().size(); j++) {
Task parent = (Task) node.getParentList().get(j);
String pName = parent.getType();
if (pName.equals("mBackground") || pName.equals("mShrink")) {
j--;
node.getParentList().remove(parent);
parent.getChildList().remove(node);
}
} break;
}
}
}
}