/* * Eoulsan development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public License version 2.1 or * later and CeCILL-C. This should be distributed with the code. * If you do not have a copy, see: * * http://www.gnu.org/licenses/lgpl-2.1.txt * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt * * Copyright for this code is held jointly by the Genomic platform * of the Institut de Biologie de l'École normale supérieure and * the individual authors. These should be listed in @author doc * comments. * * For more information on the Eoulsan project and its aims, * or to join the Eoulsan Google group, visit the home page * at: * * http://outils.genomique.biologie.ens.fr/eoulsan * */ package fr.ens.biologie.genomique.eoulsan.core.workflow; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import com.google.common.base.Preconditions; import fr.ens.biologie.genomique.eoulsan.core.TaskResult; import fr.ens.biologie.genomique.eoulsan.core.TaskStatus; import fr.ens.biologie.genomique.eoulsan.util.Reporter; /** * This class define a task status. * @author Laurent Jourdren * @since 2.0 */ public class TaskStatusImpl implements TaskStatus { private final TaskContextImpl context; private final StepStatus status; private String message; private final Map<String, Long> counters = new HashMap<>(); private String taskDescription; private double progress; private TaskResultImpl result; private Date startDate; private Date endDate; private final SerializableStopwatch stopwatch = new SerializableStopwatch(); // // Getters // @Override public String getProgressMessage() { return this.message; } @Override public Map<String, Long> getCounters() { return Collections.unmodifiableMap(this.counters); } @Override public String getDescription() { return this.taskDescription; } @Override public double getProgress() { return this.progress; } // // Setters // @Override public void setProgressMessage(final String message) { synchronized (this) { this.message = message; } } @Override public void setDescription(final String description) { checkNotNull(description, "the description argument cannot be null"); synchronized (this) { this.taskDescription = description; } } @Override public void setCounters(final Reporter reporter, final String counterGroup) { checkNotNull(reporter, "Reporter is null"); checkNotNull(counterGroup, "Counter group is null"); // Add all counters for (String counterName : reporter.getCounterNames(counterGroup)) { synchronized (this.counters) { this.counters.put(counterName, reporter.getCounterValue(counterGroup, counterName)); } } } @Override public void setProgress(final int min, final int max, final int value) { checkProgress(min, max, value); if (min == max) { setProgress(1.0); } else { setProgress(((double) (value - min)) / (max - min)); } } @Override public void setProgress(final double progress) { // Check result state checkResultState(); // Check progress value checkProgress(progress); synchronized (this) { // Set progress value this.progress = progress; // If a status for the step exist, inform the step status if (this.status != null) { this.status.setTaskProgress(this.context.getId(), this.context.getContextName(), progress); } } } // // Step result creation // /** * Stop the step. * @return the duration of the step in milliseconds */ private long endOfStep() { checkState(this.startDate != null, "stopwatch has been never started"); // If an exception is thrown while creating StepResult object or after, this // method // can be called two times if (this.stopwatch.isRunning()) { // Stop the stopwatch this.stopwatch.stop(); // Get the end Date this.endDate = new Date(System.currentTimeMillis()); // The step is completed setProgress(1.0); } checkState(this.endDate != null, "stopwatch has been never stopped"); // Compute elapsed time return this.stopwatch.elapsed(TimeUnit.MILLISECONDS); } @Override public TaskResult createTaskResult() { return createTaskResult(true); } @Override public TaskResult createTaskResult(final boolean success) { // Check result state checkResultState(); // Get the duration of the context execution final long duration = endOfStep(); // Create the context result this.result = new TaskResultImpl(this.context, this.startDate, this.endDate, duration, this.message, this.taskDescription == null ? "" : this.taskDescription, this.counters, success); return this.result; } @Override public TaskResult createTaskResult(final Throwable exception, final String exceptionMessage) { // Check result state checkResultState(); // Get the duration of the context execution final long duration = endOfStep(); // Create the context result this.result = new TaskResultImpl(this.context, this.startDate, this.endDate, duration, exception, exceptionMessage); return this.result; } @Override public TaskResult createTaskResult(final Throwable exception) { return createTaskResult(exception, exception.getMessage()); } // // Utility methods // /** * Check the state of the result creation. */ private void checkResultState() { checkState(this.result == null, "Step result has been created"); } /** * Check progress value. * @param progress the progress value to test */ private static void checkProgress(final double progress) { checkArgument(progress >= 0.0, "Progress is lower than 0: " + progress); checkArgument(progress <= 1.0, "Progress is greater than 1: " + progress); checkArgument(!Double.isInfinite(progress), "Progress is infinite"); checkArgument(!Double.isNaN(progress), "Progress is NaN"); } /** * Check progress value. * @param min minimal value * @param max maximal value * @param value value to test */ private static void checkProgress(final int min, final int max, final int value) { checkArgument(min <= max, "Max is lower than min"); checkArgument(min <= value, "Value is lower than min"); checkArgument(value <= max, "Value is greater than max"); } // // Other methods // /** * Start the timer. */ void durationStart() { // Get the start date this.startDate = new Date(System.currentTimeMillis()); // Start stopWatch this.stopwatch.start(); } // // Constructors // /** * Constructor. * @param taskContext the task context object * @param status the status object */ TaskStatusImpl(final TaskContextImpl taskContext, final StepStatus status) { Preconditions.checkNotNull(taskContext, "context cannot be null"); this.context = taskContext; this.status = status; } }