package edu.washington.escience.myria.parallel; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandler.Sharable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.washington.escience.myria.parallel.Worker.QueryCommand; import edu.washington.escience.myria.parallel.ipc.IPCMessage; import edu.washington.escience.myria.parallel.ipc.ShortMessageProcessor; import edu.washington.escience.myria.proto.ControlProto.ControlMessage; import edu.washington.escience.myria.proto.QueryProto.QueryMessage; import edu.washington.escience.myria.proto.QueryProto.QueryMessage.Type; import edu.washington.escience.myria.proto.TransportProto.TransportMessage; import edu.washington.escience.myria.util.AttachmentableAdapter; /** * Message handler for workers. * */ @Sharable public final class WorkerShortMessageProcessor extends AttachmentableAdapter implements ShortMessageProcessor<TransportMessage> { /** * The logger for this class. * */ private static final Logger LOGGER = LoggerFactory.getLogger(WorkerShortMessageProcessor.class); /** * * The worker who owns this handler. * * */ private final Worker ownerWorker; /** * @param ownerWorker the owner worker. * */ WorkerShortMessageProcessor(final Worker ownerWorker) { this.ownerWorker = ownerWorker; } @Override public boolean processMessage(final Channel ch, final IPCMessage.Data<TransportMessage> message) { Object o = message.getPayload(); if (!(o instanceof TransportMessage)) { return true; } TransportMessage tm = (TransportMessage) o; if (tm.getType() == TransportMessage.Type.QUERY) { return processQueryMessage(ch, message.getRemoteID(), tm.getQueryMessage()); } else if (tm.getType() == TransportMessage.Type.CONTROL) { return processControlMessage(ch, message.getRemoteID(), tm.getControlMessage()); } if (LOGGER.isErrorEnabled()) { LOGGER.error("Unknown message type :" + message); } return false; } /** * @param ch message channel * @param remoteID message source worker * @param qm the query message * @return if the message is successfully processed. * */ private boolean processQueryMessage(final Channel ch, final int remoteID, final QueryMessage qm) { SubQueryId subQueryId = new SubQueryId(qm.getQueryId(), qm.getSubqueryId()); WorkerSubQuery q = null; if (qm.getType() == Type.QUERY_DISTRIBUTE) { // new received query. ObjectInputStream osis = null; try { osis = new ObjectInputStream(new ByteArrayInputStream(qm.getQuery().getQuery().toByteArray())); final SubQueryPlan operators = (SubQueryPlan) (osis.readObject()); q = new WorkerSubQuery(operators, subQueryId, ownerWorker); if (!ownerWorker.getQueryQueue().offer(new QueryCommand(q, qm))) { return false; } } catch (IOException | ClassNotFoundException e) { LOGGER.error("Error decoding query", e); } } else { q = ownerWorker.getActiveQueries().get(subQueryId); if (q == null) { if (LOGGER.isErrorEnabled()) { LOGGER.error( "In receiving message {}, unknown query id: {}, current active queries are: {}", qm, subQueryId, ownerWorker.getActiveQueries().keySet()); } } else { if (!ownerWorker.getQueryQueue().offer(new QueryCommand(q, qm))) { return false; } } } return true; } /** * @param ch message channel * @param remoteID message source worker * @param cm the control message * @return if the message is successfully processed. * */ private boolean processControlMessage( final Channel ch, final int remoteID, final ControlMessage cm) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Control message received: " + cm); } return ownerWorker.getControlMessageQueue().offer(cm); } }