/**
* 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.failure;
import org.apache.commons.math3.distribution.GammaDistribution;
import org.apache.commons.math3.distribution.LogNormalDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.cloudbus.cloudsim.Cloudlet;
import org.workflowsim.Job;
import org.workflowsim.Task;
import org.apache.commons.math3.distribution.WeibullDistribution;
import org.workflowsim.utils.DistributionGenerator;
/**
* FailureGenerator creates a failure when a job returns
*
* @author Weiwei Chen
* @since WorkflowSim Toolkit 1.0
* @date Apr 9, 2013
*/
public class FailureGenerator {
/**
* FailureGenerator doubles the size of distribution samples each time
* but only limits to maxFailureSizeExtension. Otherwise your failure rate
* is too high for this workflow
*/
private static final int maxFailureSizeExtension = 50;
private static int failureSizeExtension = 0;
private static final boolean hasChangeTime = false;
/**
*
* @param alpha
* @param beta
* @return
*/
protected static RealDistribution getDistribution(double alpha, double beta) {
RealDistribution distribution = null;
switch (FailureParameters.getFailureDistribution()) {
case LOGNORMAL:
distribution = new LogNormalDistribution(1.0 / alpha, beta);
break;
case WEIBULL:
distribution = new WeibullDistribution(beta, 1.0 / alpha);
break;
case GAMMA:
distribution = new GammaDistribution(beta, 1.0 / alpha);
break;
case NORMAL:
//beta is the std, 1.0/alpha is the mean
distribution = new NormalDistribution(1.0 / alpha, beta);
break;
default:
break;
}
return distribution;
}
protected static void initFailureSamples() {
}
/**
* Initialize a Failure Generator.
*/
public static void init() {
initFailureSamples();
}
protected static boolean checkFailureStatus(Task task, int vmId) throws Exception {
DistributionGenerator generator;
switch (FailureParameters.getFailureGeneratorMode()) {
/**
* Every task follows the same distribution.
*/
case FAILURE_ALL:
generator = FailureParameters.getGenerator(0, 0);
break;
/**
* Generate failures based on the type of job.
*/
case FAILURE_JOB:
generator = FailureParameters.getGenerator(0, task.getDepth());
break;
/**
* Generate failures based on the index of vm.
*/
case FAILURE_VM:
generator = FailureParameters.getGenerator(vmId, 0);
break;
/**
* Generator failures based on vmId and level both
*/
case FAILURE_VM_JOB:
generator = FailureParameters.getGenerator(vmId, task.getDepth());
break;
default:
return false;
}
double start = task.getExecStartTime();
double end = task.getTaskFinishTime();
double[] samples = generator.getCumulativeSamples();
while (samples[samples.length - 1] < start) {
generator.extendSamples();
samples = generator.getCumulativeSamples();
failureSizeExtension++;
if (failureSizeExtension >= maxFailureSizeExtension) {
throw new Exception("Error rate is too high such that the simulator terminates");
}
}
for (int sampleId = 0; sampleId < samples.length; sampleId++) {
if (end < samples[sampleId]) {
//no failure
return false;
}
if (start <= samples[sampleId]) {
//has a failure
/** The idea is we need to update the cursor in generator**/
generator.getNextSample();
return true;
}
}
return false;
}
/**
* Generates a failure or not
*
* @param job
* @return whether it fails
*/
//true means has failure
//false means no failure
public static boolean generate(Job job) {
boolean jobFailed = false;
if (FailureParameters.getFailureGeneratorMode() == FailureParameters.FTCFailure.FAILURE_NONE) {
return jobFailed;
}
try {
for (Task task : job.getTaskList()) {
int failedTaskSum = 0;
if (checkFailureStatus(task, job.getVmId())) {
//this task fail
jobFailed = true;
failedTaskSum++;
task.setCloudletStatus(Cloudlet.FAILED);
}
FailureRecord record = new FailureRecord(0, failedTaskSum, task.getDepth(), 1, job.getVmId(), task.getCloudletId(), job.getUserId());
FailureMonitor.postFailureRecord(record);
}
if (jobFailed) {
job.setCloudletStatus(Cloudlet.FAILED);
} else {
job.setCloudletStatus(Cloudlet.SUCCESS);
}
} catch (Exception e) {
e.printStackTrace();
}
return jobFailed;
}
}