package org.akka.essentials.grid.controller;
import java.util.HashMap;
import java.util.Map;
import org.akka.essentials.grid.StartWorker;
import org.akka.essentials.grid.StopWorker;
import org.akka.essentials.grid.Task;
import org.akka.essentials.grid.TaskFinished;
import org.akka.essentials.grid.worker.WorkerActor;
import akka.actor.ActorRef;
import akka.actor.Address;
import akka.actor.AddressFromURIString;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.remote.routing.RemoteRouterConfig;
import akka.routing.RoundRobinRouter;
public class JobControllerActor extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
private ActorRef workerRouterActor = null;
private Map<String, Address> workerAddressMap = new HashMap<String, Address>();
private static int count = 0;
private ActorRef workSchedulerActor;
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof StartWorker) {
log.info("Received worker registration request");
addWorkerRoute(((StartWorker) message).getActorPath());
log.info("worker router updated for the new address");
workSchedulerActor.tell("You can start sending work!", getContext()
.self());
} else if (message instanceof String) {
if (((String) message).compareTo("SendWork") == 0) {
log.info("About to send work packets to workers");
if (workerRouterActor != null) {
for (int i = 0; i < workerAddressMap.size(); i++) {
count++;
workerRouterActor.tell(new Task(count), this.getSelf());
}
log.info("Work Packets send upto->" + count);
// let the workscheduler know that you finished with sending
// work packets
workSchedulerActor.tell("Work Packets send", getContext()
.self());
} else {
log.info("No workers registered as of now!");
// tell the workscheduler actor to wake me up in 5 secs
// again
workSchedulerActor.tell(Integer.valueOf(5), getContext()
.self());
}
} else if (((String) message).compareTo("Enough!") == 0) {
log.info("Worker requesting shutdown"
+ getSender().path().toString());
// TODO shut down the routee at this point and remote the
// routerconfig
}
} else if (message instanceof TaskFinished) {
log.info("Task finished->"
+ ((TaskFinished) message).getTaskNumber());
} else if (message instanceof StopWorker) {
StopWorker stopMe = (StopWorker) message;
log.info("Worker requesting shutdown->" + stopMe.getActorPath());
removeWorkerRoute(stopMe.getActorPath());
}
}
public JobControllerActor(ActorRef inWorkSchedulerActor) {
workSchedulerActor = inWorkSchedulerActor;
}
/**
* Add the new worker to the router mechanism
*
* @param address
*/
private void addWorkerRoute(String address) {
// send the stop message to all the worker actors
if (workerRouterActor != null) {
for (int i = 0; i < workerAddressMap.size(); i++)
workerRouterActor.tell("STOP");
}
// add the address to the Map
workerAddressMap.put(address, AddressFromURIString.parse(address));
Address[] addressNodes = new Address[workerAddressMap.size()];
Address[] workerAddress = workerAddressMap.values().toArray(
addressNodes);
// update the workerRouter actor with the information on all workers
workerRouterActor = getContext().system().actorOf(
new Props(WorkerActor.class).withRouter(new RemoteRouterConfig(
new RoundRobinRouter(workerAddress.length),
workerAddress)));
}
private void removeWorkerRoute(String address) {
//check if the address is registered or not
if (workerRouterActor != null) {
if (!workerAddressMap.containsKey(address)) {
return;
}
}
log.info("Processing Worker shutdown request->" + address);
if (workerRouterActor != null) {
for (int i = 0; i < workerAddressMap.size(); i++)
if (!workerRouterActor.isTerminated())
workerRouterActor.tell("STOP");
}
if (workerAddressMap.size() > 0)
workerAddressMap.remove(address);
if (workerAddressMap.size() > 0) {
Address[] addressNodes = new Address[workerAddressMap.size()];
Address[] workerAddress = workerAddressMap.values().toArray(
addressNodes);
workerRouterActor = getContext().system().actorOf(
new Props(WorkerActor.class)
.withRouter(new RemoteRouterConfig(
new RoundRobinRouter(workerAddress.length),
workerAddress)));
} else
workerRouterActor = null;
}
}