package edu.washington.escience.myria.parallel;
import java.io.IOException;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandler.Sharable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.protobuf.CodedInputStream;
import edu.washington.escience.myria.MyriaConstants;
import edu.washington.escience.myria.parallel.ipc.PayloadSerializer;
import edu.washington.escience.myria.proto.TransportProto.TransportMessage;
import edu.washington.escience.myria.storage.TupleBatch;
import edu.washington.escience.myria.util.IPCUtils;
/**
* This class monitors all the input/output IPC data. It makes sure that all input data are of {@link TransportMessage}
* type. And it does all IPC exception catching and recording.
* */
@Sharable
public class TransportMessageSerializer implements PayloadSerializer {
/** The logger for this class. */
protected static final Logger LOGGER = LoggerFactory.getLogger(TransportMessageSerializer.class);
@Override
public final ChannelBuffer serialize(final Object m) {
Preconditions.checkNotNull(m);
// m has only 3 possibilities:
if (m instanceof TransportMessage) {
// case 1: TransportMessage.QUERY
// case 2: TransportMessage.CONTROL
// TransportMessage.DATA is not possible to occur here
return ChannelBuffers.wrappedBuffer(((TransportMessage) m).toByteArray());
} else if (m instanceof TupleBatch) {
// case 3: TupleBatch
TupleBatch tb = (TupleBatch) m;
if (!tb.isEOI()) {
return ChannelBuffers.wrappedBuffer(((TupleBatch) m).toTransportMessage().toByteArray());
} else {
return ChannelBuffers.wrappedBuffer(IPCUtils.EOI.toByteArray());
}
} else {
throw new IllegalArgumentException(
MyriaConstants.SYSTEM_NAME
+ " IPC only supports "
+ TransportMessage.class.getSimpleName()
+ " and "
+ TupleBatch.class.getSimpleName()
+ ", but received a message of type: "
+ m.getClass().getCanonicalName());
}
}
/**
* @param buf input data buffer.
* @return Deserialized transport message
* @throws IOException if any IO errors.
*/
private TransportMessage deSerializeTransportMessage(final ChannelBuffer buf) throws IOException {
final byte[] array;
final int offset;
final int length = buf.readableBytes();
if (buf.hasArray()) {
array = buf.array();
offset = buf.arrayOffset() + buf.readerIndex();
} else {
array = new byte[length];
buf.getBytes(buf.readerIndex(), array, 0, length);
offset = 0;
}
CodedInputStream cis = CodedInputStream.newInstance(array, offset, length);
return TransportMessage.parseFrom(cis);
}
@Override
public final Object deSerialize(
final ChannelBuffer buffer, final Object processor, final Object att) throws IOException {
TransportMessage tm = deSerializeTransportMessage(buffer);
return tm;
}
}