package cz.cuni.mff.d3s.been.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cz.cuni.mff.d3s.been.cluster.context.ClusterContext;
import cz.cuni.mff.d3s.been.manager.action.TaskAction;
import cz.cuni.mff.d3s.been.manager.action.TaskActionException;
import cz.cuni.mff.d3s.been.manager.msg.TaskMessage;
import cz.cuni.mff.d3s.been.mq.IMessageReceiver;
import cz.cuni.mff.d3s.been.mq.IMessageSender;
import cz.cuni.mff.d3s.been.mq.MessageQueues;
import cz.cuni.mff.d3s.been.mq.MessagingException;
/**
* @author Martin Sixta
*/
final class TaskMessageProcessor extends Thread {
private static Logger log = LoggerFactory.getLogger(TaskMessageProcessor.class);
private final ClusterContext clusterCtx;
private final MessageQueues messageQueues = MessageQueues.getInstance();
/**
* Creates TaskMessageProcessor.
*
* @param clusterCtx
* connection to the cluster
*/
public TaskMessageProcessor(ClusterContext clusterCtx) {
this.clusterCtx = clusterCtx;
}
@Override
public void run() {
final IMessageReceiver<TaskMessage> receiver;
try {
receiver = messageQueues.getReceiver(TaskManagerNames.ACTION_QUEUE_NAME);
} catch (MessagingException e) {
log.error("Cannot obtain reference to {} queue", TaskManagerNames.ACTION_QUEUE_NAME);
return;
}
while (!Thread.interrupted()) {
try {
TaskMessage message = receiver.receive();
if (message instanceof PoisonMessage) {
log.info("Poison received, exiting");
break;
}
log.debug("Task message of type '{}' received", message.getClass());
TaskAction action = message.createAction(clusterCtx);
if (action != null) {
action.execute();
}
} catch (MessagingException e) {
log.error("Cannot receive a message", e);
} catch (TaskActionException e) {
log.error("Cannot execute action for received message", e);
} catch (Exception e) {
log.error("Unknown error", e);
}
}
log.info("Exiting thread of {}", TaskMessageProcessor.class.getSimpleName());
}
/**
*
*
*/
public void poison() {
try {
IMessageSender<TaskMessage> sender = messageQueues.createSender(TaskManagerNames.ACTION_QUEUE_NAME);
sender.send(new PoisonMessage());
sender.close();
this.join();
} catch (MessagingException | InterruptedException e) {
log.error("Cannot stop Task Message Processor.", e);
} finally {
try {
messageQueues.terminate(TaskManagerNames.ACTION_QUEUE_NAME);
} catch (MessagingException e) {
log.error("Error terminating message queue", e);
}
}
}
/**
* Message used to terminate task message processing.
*/
private static final class PoisonMessage implements TaskMessage {
@Override
public TaskAction createAction(ClusterContext ctx) {
throw new UnsupportedOperationException("Poison message does not execute actions!");
}
}
}