package com.revolsys.parallel.process;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import com.revolsys.parallel.ThreadInterruptedException;
import com.revolsys.parallel.ThreadUtil;
public abstract class AbstractResetableProcess extends AbstractProcess {
private final Set<UUID> executions = new LinkedHashSet<>();
private boolean pause = false;
private boolean reset = false;
private boolean running = false;
private String status = "initialized";
private boolean waitForExecutionToFinish = false;
private long waitTime = 1000;
public AbstractResetableProcess() {
}
public AbstractResetableProcess(final long waitTime) {
this.waitTime = waitTime;
}
protected abstract boolean execute();
protected void finishExecution(final UUID id) {
synchronized (this.executions) {
this.executions.remove(id);
this.executions.notifyAll();
}
}
@ManagedAttribute
public int getExecutionCount() {
return this.executions.size();
}
@ManagedAttribute
public String getStatus() {
return this.status;
}
public long getWaitTime() {
return this.waitTime;
}
/**
* The hard reset causes the scheduler loop to restart ignoring all current
* executing requests. Upon reset the counts of executing requests and the
* status of all jobs will be updated to ensure consistency.
*/
@ManagedOperation
public void hardReset() {
this.waitForExecutionToFinish = false;
this.pause = false;
this.reset = true;
}
/**
* The pause causes the scheduler to sleep until a soft or hard reset is
* initiated.
*/
@ManagedOperation
public void pause() {
this.pause = true;
}
protected void postRun() {
}
protected void preRun() {
}
protected void reset() {
}
@Override
public void run() {
preRun();
this.running = true;
try {
while (this.running) {
this.status = "resetting";
this.executions.clear();
reset();
this.reset = false;
while (this.running && !this.reset) {
this.status = "starting execution";
if (this.pause || !execute()) {
if (this.pause) {
this.status = "paused";
} else {
this.status = "waiting";
}
ThreadUtil.pause(this, this.waitTime);
}
}
synchronized (this.executions) {
while (this.waitForExecutionToFinish && !this.executions.isEmpty()) {
waitOnExecutions();
}
}
}
} catch (final ThreadInterruptedException e) {
} finally {
try {
postRun();
} finally {
this.running = false;
this.status = "terminated";
}
}
}
protected void setStatus(final String status) {
this.status = status;
}
public void setWaitTime(final long waitTime) {
this.waitTime = waitTime;
}
/**
* The soft reset causes the scheduler loop to restart after all current
* executing requests have completed. Upon reset the counts of executing
* requests and the status of all jobs will be updated to ensure consistency.
*/
@ManagedOperation
public void softReset() {
this.waitForExecutionToFinish = true;
this.pause = false;
this.reset = true;
}
protected UUID startExecution() {
synchronized (this.executions) {
final UUID id = UUID.randomUUID();
this.executions.add(id);
this.executions.notifyAll();
return id;
}
}
protected void waitOnExecutions() {
this.status = "waiting on executions";
ThreadUtil.pause(this.executions, this.waitTime);
}
}