/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.core.plugins.orchestrate.akka.distributed;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import org.roda.core.plugins.orchestrate.akka.distributed.Master.Work;
public final class WorkState {
private final Map<String, Work> workInProgress;
private final Set<String> acceptedWorkIds;
private final Set<String> doneWorkIds;
private final ConcurrentLinkedDeque<Work> pendingWork;
public WorkState updated(WorkDomainEvent event) {
WorkState newState = null;
if (event instanceof WorkAccepted) {
return new WorkState(this, (WorkAccepted) event);
} else if (event instanceof WorkStarted) {
return new WorkState(this, (WorkStarted) event);
} else if (event instanceof WorkCompleted) {
return new WorkState(this, (WorkCompleted) event);
} else if (event instanceof WorkerFailed) {
return new WorkState(this, (WorkerFailed) event);
} else if (event instanceof WorkerTimedOut) {
return new WorkState(this, (WorkerTimedOut) event);
}
return newState;
}
public WorkState() {
workInProgress = new HashMap<>();
acceptedWorkIds = new HashSet<>();
doneWorkIds = new HashSet<>();
pendingWork = new ConcurrentLinkedDeque<>();
}
private WorkState(WorkState workState, WorkAccepted workAccepted) {
ConcurrentLinkedDeque<Work> tmp_pendingWork = new ConcurrentLinkedDeque<>(workState.pendingWork);
Set<String> tmp_acceptedWorkIds = new HashSet<>(workState.acceptedWorkIds);
tmp_pendingWork.addLast(workAccepted.work);
tmp_acceptedWorkIds.add(workAccepted.work.workId);
workInProgress = new HashMap<>(workState.workInProgress);
acceptedWorkIds = tmp_acceptedWorkIds;
doneWorkIds = new HashSet<>(workState.doneWorkIds);
pendingWork = tmp_pendingWork;
}
public WorkState(WorkState workState, WorkStarted workStarted) {
ConcurrentLinkedDeque<Work> tmp_pendingWork = new ConcurrentLinkedDeque<>(workState.pendingWork);
Map<String, Work> tmp_workInProgress = new HashMap<>(workState.workInProgress);
Work work = tmp_pendingWork.removeFirst();
if (!work.workId.equals(workStarted.workId)) {
throw new IllegalArgumentException("WorkStarted expected workId " + work.workId + "==" + workStarted.workId);
}
tmp_workInProgress.put(work.workId, work);
workInProgress = tmp_workInProgress;
acceptedWorkIds = new HashSet<>(workState.acceptedWorkIds);
doneWorkIds = new HashSet<>(workState.doneWorkIds);
pendingWork = tmp_pendingWork;
}
public WorkState(WorkState workState, WorkCompleted workCompleted) {
Map<String, Work> tmp_workInProgress = new HashMap<>(workState.workInProgress);
Set<String> tmp_doneWorkIds = new HashSet<>(workState.doneWorkIds);
tmp_workInProgress.remove(workCompleted.workId);
tmp_doneWorkIds.add(workCompleted.workId);
workInProgress = tmp_workInProgress;
acceptedWorkIds = new HashSet<>(workState.acceptedWorkIds);
doneWorkIds = tmp_doneWorkIds;
pendingWork = new ConcurrentLinkedDeque<>(workState.pendingWork);
}
public WorkState(WorkState workState, WorkerFailed workerFailed) {
Map<String, Work> tmp_workInProgress = new HashMap<>(workState.workInProgress);
ConcurrentLinkedDeque<Work> tmp_pendingWork = new ConcurrentLinkedDeque<>(workState.pendingWork);
tmp_pendingWork.addLast(workState.workInProgress.get(workerFailed.workId));
tmp_workInProgress.remove(workerFailed.workId);
workInProgress = tmp_workInProgress;
acceptedWorkIds = new HashSet<>(workState.acceptedWorkIds);
doneWorkIds = new HashSet<>(workState.doneWorkIds);
pendingWork = tmp_pendingWork;
}
public WorkState(WorkState workState, WorkerTimedOut workerTimedOut) {
Map<String, Work> tmp_workInProgress = new HashMap<>(workState.workInProgress);
ConcurrentLinkedDeque<Work> tmp_pendingWork = new ConcurrentLinkedDeque<>(workState.pendingWork);
tmp_pendingWork.addLast(workState.workInProgress.get(workerTimedOut.workId));
tmp_workInProgress.remove(workerTimedOut.workId);
workInProgress = tmp_workInProgress;
acceptedWorkIds = new HashSet<>(workState.acceptedWorkIds);
doneWorkIds = new HashSet<>(workState.doneWorkIds);
pendingWork = tmp_pendingWork;
}
@Override
public String toString() {
return Integer.toString(acceptedWorkIds.size());
}
public Work nextWork() {
return pendingWork.getFirst();
}
public boolean hasWork() {
return !pendingWork.isEmpty();
}
public boolean isAccepted(String workId) {
return acceptedWorkIds.contains(workId);
}
public boolean isInProgress(String workId) {
return workInProgress.containsKey(workId);
}
public boolean isDone(String workId) {
return doneWorkIds.contains(workId);
}
public interface WorkDomainEvent {
}
public static final class WorkAccepted implements WorkDomainEvent, Serializable {
private static final long serialVersionUID = -3030209712968228650L;
final Work work;
public WorkAccepted(Work work) {
this.work = work;
}
}
public static final class WorkStarted implements WorkDomainEvent, Serializable {
private static final long serialVersionUID = 5143608113160395981L;
final String workId;
public WorkStarted(String workId) {
this.workId = workId;
}
}
public static final class WorkCompleted implements WorkDomainEvent, Serializable {
private static final long serialVersionUID = -551011155695164520L;
final String workId;
final Object result;
public WorkCompleted(String workId, Object result) {
this.workId = workId;
this.result = result;
}
}
public static final class WorkerFailed implements WorkDomainEvent, Serializable {
private static final long serialVersionUID = 6671821443961398568L;
final String workId;
public WorkerFailed(String workId) {
this.workId = workId;
}
}
public static final class WorkerTimedOut implements WorkDomainEvent, Serializable {
private static final long serialVersionUID = -1080174696275300604L;
final String workId;
public WorkerTimedOut(String workId) {
this.workId = workId;
}
}
}