package eu.appsatori.pipes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
class DevPipeDatastore implements PipeDatastore {
private static class TaskMetadata {
AtomicBoolean allTaskStarted;
AtomicBoolean active;
AtomicInteger totalCount;
Map<Integer, Object> results;
AtomicInteger count;
Map<Integer, Boolean> finished;
}
private static final Random RANDOM = new Random();
ConcurrentMap<String, Object> stash = new ConcurrentHashMap<String, Object>();
ConcurrentMap<String, TaskMetadata> tasks = new ConcurrentHashMap<String, TaskMetadata>();
public String stashArgument(Object argument) {
if(argument == null){
return "";
}
String key = argument.toString() + RANDOM.nextLong();
stash.put(key, argument);
return key;
}
public Object retrieveArgument(String path) {
return stash.get(path);
}
public boolean isActive(String taskId) {
TaskMetadata task = tasks.get(taskId);
if(task == null){
return false;
}
return task.active.get();
}
public boolean setActive(String taskId, boolean active) {
TaskMetadata task = null;
task = tasks.get(taskId);
if(task == null){
return false;
}
task.active.set(active);
return true;
}
public int logTaskStarted(String taskId) {
TaskMetadata task = tasks.get(taskId);
if(task != null){
if(task.allTaskStarted.get()){
throw new IllegalStateException("No more tasks expected!");
}
int current = task.totalCount.incrementAndGet();
task.count.incrementAndGet();
return current -1;
}
task = new TaskMetadata();
task.active = new AtomicBoolean(true);
task.totalCount = new AtomicInteger(1);
task.count = new AtomicInteger(1);
task.results = new TreeMap<Integer, Object>();
task.finished = new TreeMap<Integer, Boolean>();
task.allTaskStarted = new AtomicBoolean();
tasks.putIfAbsent(taskId, task);
return 0;
}
public int logAllTasksStarted(String taskId) {
TaskMetadata task = tasks.get(taskId);
if(task == null){
throw new IllegalArgumentException("Task " + taskId + " doesn't exist!");
}
task.allTaskStarted.set(true);
return task.totalCount.get();
}
public boolean haveAllTasksStarted(String taskId) {
TaskMetadata task = tasks.get(taskId);
if(task == null){
throw new IllegalArgumentException("Task " + taskId + " doesn't exist!");
}
return task.allTaskStarted.get();
}
public int logTaskFinished(String taskId, int index, Object results) {
TaskMetadata task = tasks.get(taskId);
if(task == null){
throw new IllegalArgumentException("Node " + taskId + " hasn't been logged!");
}
if(index >= task.totalCount.get()){
throw new ArrayIndexOutOfBoundsException();
}
if(Boolean.TRUE.equals(task.finished.get(index))){
throw new IllegalStateException("Node with index " + index + " has already finished!");
}
int count = task.count.decrementAndGet();
task.results.put(index, results);
task.finished.put(index, Boolean.TRUE);
if(count == 0 && task.allTaskStarted.get()){
task.active.set(false);
}
return count;
}
public List<Object> getTaskResults(String taskId) {
TaskMetadata task = tasks.get(taskId);
if(task == null){
throw new IllegalArgumentException("Node " + taskId + " hasn't been logged!");
}
if(!task.allTaskStarted.get()){
throw new IllegalStateException("All tasks haven't started yet!");
}
if(task.count.get() != 0){
throw new IllegalStateException("All tasks haven't finished yet!");
}
List<Object> ret = new ArrayList<Object>();
for (int i = 0; i < task.totalCount.get(); i++) {
ret.add(task.results.get(i));
}
return Collections.unmodifiableList(ret);
}
public int getParallelTaskCount(String taskId) {
TaskMetadata task = tasks.get(taskId);
if (task == null) {
throw new IllegalArgumentException("Node " + taskId
+ " hasn't been logged!");
}
return task.totalCount.intValue();
}
public boolean clearTaskLog(String taskId) {
return clearTaskLog(taskId, false);
}
public boolean clearTaskLog(String taskId, boolean force) {
if(force){
TaskMetadata task = tasks.remove(taskId);
return task != null;
}
TaskMetadata task = tasks.get(taskId);
if(task == null){
return false;
}
if(task.count.intValue() != 0){
throw new IllegalStateException("All tasks haven't finished yet!");
}
task = tasks.remove(taskId);
return task != null;
}
}