com.almende.eve.scheduler.ClockSchedulerFactory Maven / Gradle / Ivy
package com.almende.eve.scheduler;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.logging.Logger;
import org.joda.time.DateTime;
import com.almende.eve.agent.Agent;
import com.almende.eve.agent.AgentFactory;
import com.almende.eve.agent.annotation.Sender;
import com.almende.eve.clock.Clock;
import com.almende.eve.clock.RunnableClock;
import com.almende.eve.rpc.RequestParams;
import com.almende.eve.rpc.jsonrpc.JSONRequest;
public class ClockSchedulerFactory implements SchedulerFactory {
Map schedulers = new HashMap();
AgentFactory agentFactory = null;
/**
* This constructor is called when constructed by the AgentFactory
*
* @param agentFactory
* @param params
*/
public ClockSchedulerFactory(AgentFactory agentFactory,
Map params) {
this(agentFactory, "");
}
public ClockSchedulerFactory(AgentFactory agentFactory, String id) {
this.agentFactory = agentFactory;
}
@Override
public Scheduler getScheduler(String agentId) {
synchronized (schedulers) {
if (schedulers.containsKey(agentId))
return schedulers.get(agentId);
Scheduler scheduler;
try {
scheduler = new ClockScheduler(agentId, agentFactory);
schedulers.put(agentId, scheduler);
return scheduler;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
@Override
public void destroyScheduler(String agentId){
synchronized(schedulers){
schedulers.remove(agentId);
}
}
}
class ClockScheduler implements Scheduler, Runnable {
final Agent myAgent;
final Clock myClock;
public ClockScheduler(String agentId, AgentFactory factory)
throws Exception {
myAgent = factory.getAgent(agentId);
if (myAgent == null) {
Logger.getLogger("ClockScheduler").severe(
"Error: Agent not found:" + agentId);
}
myClock = new RunnableClock();
TaskEntry task = getFirstTask(false);
if (task != null)
myClock.requestTrigger(agentId, task.due, this);
}
@SuppressWarnings("unchecked")
public TaskEntry getFirstTask(boolean remove) {
TreeSet timeline = (TreeSet) myAgent.getState()
.get("_taskList");
if (timeline != null && !timeline.isEmpty()) {
TaskEntry task = timeline.first();
if (remove) {
TreeSet newTimeline = (TreeSet) timeline
.clone();
newTimeline.remove(task);
if (!myAgent.getState().putIfUnchanged("_taskList",
newTimeline, timeline)) {
return getFirstTask(remove); // recursive retry......
}
}
return task;
}
return null;
}
@SuppressWarnings("unchecked")
public void putTask(TaskEntry task) {
TreeSet oldTimeline = (TreeSet) myAgent
.getState().get("_taskList");
TreeSet timeline;
if (oldTimeline == null) {
timeline = new TreeSet();
} else {
timeline = (TreeSet) oldTimeline.clone();
}
timeline.add(task);
if (!myAgent.getState().putIfUnchanged("_taskList", timeline,
oldTimeline)) {
putTask(task); // recursive retry....
return;
}
}
public void runTask(final TaskEntry task) {
myClock.runInPool(new Runnable() {
@Override
public void run() {
try {
RequestParams params = new RequestParams();
params.put(Sender.class, null); // TODO: provide itself
myAgent.getAgentFactory().invoke(myAgent.getId(),
task.request, params);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@Override
public String createTask(JSONRequest request, long delay) {
TaskEntry task = new TaskEntry(DateTime.now().plus(delay), request);
if (delay <= 0) {
runTask(task);
} else {
putTask(task);
TaskEntry first = getFirstTask(false);
if (first != null)
myClock.requestTrigger(myAgent.getId(), first.due, this);
}
return task.taskId;
}
@SuppressWarnings("unchecked")
@Override
public void cancelTask(String id) {
TreeSet oldTimeline = (TreeSet) myAgent
.getState().get("_taskList");
TreeSet timeline;
if (oldTimeline == null) {
timeline = new TreeSet();
} else {
timeline = (TreeSet) oldTimeline.clone();
}
TaskEntry[] arr = timeline.toArray(new TaskEntry[0]);
timeline.clear();
for (TaskEntry entry : arr) {
if (!entry.taskId.equals(id)) {
timeline.add(entry);
}
}
if (!myAgent.getState().putIfUnchanged("_taskList", timeline,
oldTimeline)) {
cancelTask(id); // recursive retry....
return;
}
}
@SuppressWarnings("unchecked")
@Override
public Set getTasks() {
Set result = new HashSet();
TreeSet timeline = (TreeSet) myAgent
.getState().get("_taskList");
if (timeline == null) return result;
for (TaskEntry entry : timeline){
result.add(entry.taskId);
}
return result;
}
@Override
public void run() {
TaskEntry task = getFirstTask(true);
if (task != null) {
if (task.due.isBeforeNow()) {
runTask(task);
run();// recursive call next task
return;
} else {
putTask(task);
}
myClock.requestTrigger(myAgent.getId(), task.due, this);
}
}
}
class TaskEntry implements Comparable, Serializable {
private static final long serialVersionUID = -2402975617148459433L;
// TODO, make JSONRequest.equals() state something about real equal tasks,
// use it as deduplication!
String taskId;
JSONRequest request;
DateTime due;
public TaskEntry(DateTime due, JSONRequest request) {
taskId = UUID.randomUUID().toString();
this.request = request;
this.due = due;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof TaskEntry))
return false;
TaskEntry other = (TaskEntry) o;
return taskId.equals(other.taskId);
}
@Override
public int hashCode() {
return taskId.hashCode();
}
@Override
public int compareTo(TaskEntry o) {
if (due.equals(o.due))
return 0;
return due.compareTo(o.due);
}
@Override
public String toString(){
return taskId+" ["+due+"]";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy