package com.alibaba.doris.dataserver.net.netty; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.doris.dataserver.action.data.ActionData; import com.alibaba.doris.dataserver.action.data.ErrorActionData; import com.alibaba.doris.dataserver.action.data.SupportBodyActionData; import com.alibaba.doris.dataserver.action.parser.ActionParser; import com.alibaba.doris.dataserver.net.InvalidCommandException; import com.alibaba.doris.dataserver.net.protocol.ProtocolParseExcetion; import com.alibaba.doris.dataserver.net.protocol.text.TextProtocolDecoder; /** * @author ajun Email:jack.yuj@alibaba-inc.com */ public class DataServerDecoder extends FrameDecoder { @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { if (actionData == null) { boolean breakLoop = true; ErrorActionData errorActionData = null; do { try { buffer.markReaderIndex(); actionData = decoder.readHeader(buffer); if (actionData == null) { // 如果当前数据不是一个完整的命令,则将流中的数据指针复原到起始位置。 buffer.resetReaderIndex(); return errorActionData; } if (null != errorActionData) { // 将流中的数据指针复原到第一个有效命令序列的起始位置。 buffer.resetReaderIndex(); breakLoop = true; // reset actionData, It is important. actionData = null; return errorActionData; } } catch (ProtocolParseExcetion e) { // 处理无法识别的命令序列:读下一个可识别的命令, // 通过breakLoop一直循环下去,要么读到正确的命令包, // 要么流中的数据读完。 breakLoop = false; logger.error("Decode command error.", e); if (null == errorActionData) { if (e instanceof InvalidCommandException) { errorActionData = new ErrorActionData(ErrorActionData.UNKNOWN_COMMAND); errorActionData.setErrorMessage(e.getMessage()); } else { errorActionData = new ErrorActionData(ErrorActionData.CLIENT_ERROR); } } } catch (Exception e) { breakLoop = false; logger.error("Decode command error.", e); if (null == errorActionData) { errorActionData = new ErrorActionData(ErrorActionData.CLIENT_ERROR); errorActionData.setErrorMessage(e.getMessage()); } } } while (!breakLoop); } if (actionData instanceof SupportBodyActionData) { SupportBodyActionData contentMetaData = (SupportBodyActionData) actionData; if (contentMetaData.isNeedReadBody()) { try { buffer.markReaderIndex(); byte[] bodyByteArray = decoder.readBody(buffer, contentMetaData); if (bodyByteArray == null) { buffer.resetReaderIndex(); if (logger.isDebugEnabled()) { logger.debug("Unfinished command : buffer size:" + buffer.readableBytes() + " Command:" + actionData); } return null; } ActionParser parser = actionData.getActionType().getParser(); parser.readBody(bodyByteArray, contentMetaData); } catch (Exception e) { ErrorActionData errorActionData = new ErrorActionData(ErrorActionData.CLIENT_ERROR); errorActionData.setErrorMessage(e.getMessage()); actionData = null;// It is important for actionData to be set null; return errorActionData; } } } ActionData result = actionData; actionData = null; if (logger.isDebugEnabled() && channel != null) { logger.debug("client:" + channel.getRemoteAddress() + " Server received command:" + result + " thread:" + Thread.currentThread().getName()); } return result; } private ActionData actionData; private static TextProtocolDecoder decoder = new TextProtocolDecoder(); private static final Logger logger = LoggerFactory.getLogger(DataServerDecoder.class); }