/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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 com.asakusafw.yaess.core;
import java.io.IOException;
import java.io.OutputStream;
/**
* Receives job's progress.
* @since 0.2.3
*/
public class JobMonitor implements ExecutionMonitor {
private final PhaseMonitor parent;
private final String jobId;
private final double taskSizeInParent;
private double currentTaskSize;
private double currentProgress;
private boolean closed;
/**
* Creates a new instance.
* @param parent the parent monitor
* @param jobId target job ID
* @param taskSizeInParent total task size in the parent for this monitor
* @throws IllegalArgumentException if {@code parent} is {@code null}
*/
public JobMonitor(PhaseMonitor parent, String jobId, double taskSizeInParent) {
if (parent == null) {
throw new IllegalArgumentException("parent must not be null"); //$NON-NLS-1$
}
if (jobId == null) {
throw new IllegalArgumentException("jobId must not be null"); //$NON-NLS-1$
}
this.parent = parent;
this.jobId = jobId;
this.taskSizeInParent = taskSizeInParent;
}
@Override
public void checkCancelled() throws InterruptedException {
parent.checkCancelled();
}
/**
* Begins a task and notify this event to the corresponding receiver.
* This method can be invoked once for each object.
* @param taskSize the total task size
* @throws IOException if failed to notify this event
* @throws IllegalArgumentException if some parameters were {@code null}
*/
@Override
public synchronized void open(double taskSize) throws IOException {
if (taskSize <= 0) {
throw new IllegalArgumentException("taskSize must be > 0"); //$NON-NLS-1$
}
this.currentTaskSize = taskSize;
parent.onJobMonitorOpened(jobId);
}
@Override
public synchronized void progressed(double size) throws IOException {
double nextProgress = currentProgress + size;
changeCurrentProgress(nextProgress);
}
@Override
public synchronized void setProgress(double workedSize) throws IOException {
changeCurrentProgress(workedSize);
}
@Override
public OutputStream getOutput() throws IOException {
return parent.getJobOutput(jobId);
}
@Override
public synchronized void close() throws IOException {
changeCurrentProgress(currentTaskSize);
parent.onJobMonitorClosed(jobId);
}
private void changeCurrentProgress(double nextProgress) throws IOException {
if (closed) {
return;
}
closed = true;
if (taskSizeInParent == 0) {
return;
}
double normalized = Math.max(0, Math.min(currentTaskSize, nextProgress));
assert 0 <= normalized && normalized <= currentTaskSize;
double delta = normalized - currentProgress;
double deltaInParent = delta / taskSizeInParent;
currentProgress = normalized;
if (deltaInParent != 0) {
parent.progressed(deltaInParent);
}
}
}