package com.alibaba.doris.client.net.protocol.text; import org.jboss.netty.buffer.ChannelBuffer; import com.alibaba.doris.client.net.NetException; import com.alibaba.doris.client.net.command.Command; import com.alibaba.doris.client.net.command.GetCommand; import com.alibaba.doris.client.net.command.GetCommand.PhaseStructure; import com.alibaba.doris.common.data.Key; import com.alibaba.doris.common.data.Value; import com.alibaba.doris.common.data.impl.NullValueImpl; import com.alibaba.doris.common.data.impl.ValueImpl; import com.alibaba.doris.common.data.util.ByteUtils; /** * @author ajun Email:jack.yuj@alibaba-inc.com */ public class GetProtocolParser extends TextProtocolParser { public void encode(Command<?> commandData, ChannelBuffer buffer) { GetCommand get = (GetCommand) commandData; Key key = get.getKey(); if (null != key) { byte[] keyBytes = key.getPhysicalKeyBytes(); long routeVersion = key.getRouteVersion(); byte[] vnodeBytes = ByteUtils.stringToByte(Integer.toString(key.getVNode(), 10)); byte[] routeVersionBytes = ByteUtils.stringToByte(String.valueOf(routeVersion)); assemableCommandData(buffer, GET, keyBytes, routeVersionBytes, vnodeBytes); } } public boolean decode(Command<?> commandData, ChannelBuffer buffer) { GetCommand get = (GetCommand) commandData; PhaseStructure currentPhase = get.getCurrentPhase(); while (true) { boolean needBreak = false; switch (currentPhase) { case HEAD: { buffer.markReaderIndex(); byte[] line = readLine(buffer); if (line == null) { // 流中的数据已经读完,但本命令的数据还没读完,返回。 needBreak = true; buffer.resetReaderIndex(); break; } parseHead(line, get); if (get.isSuccess()) { needBreak = true; } else { currentPhase = PhaseStructure.DATA; get.setCurrentPhase(currentPhase); } break; } case DATA: { buffer.markReaderIndex(); if (!readData(buffer, get)) { // 还没读完数据。 needBreak = true; buffer.resetReaderIndex(); break; } currentPhase = PhaseStructure.END; get.setCurrentPhase(currentPhase); break; } case END: { buffer.markReaderIndex(); byte[] line = readLine(buffer); if (line == null) { // 流中的数据已经读完,但本命令的数据还没读完,返回。 needBreak = true; buffer.resetReaderIndex(); break; } if (checkIsEndFlag(line)) { get.setSuccess(true); needBreak = true; break; } throw new NetException("Invalid byte stream. Couldn't find the end flag. [" + get + "]"); } default: break; } if (needBreak) { break; } } if (get.isSuccess()) { return true; } return false; } protected boolean readData(ChannelBuffer buffer, GetCommand command) { int remain = buffer.readableBytes(); if (remain == 0) { return false; } int length = command.getValueBytes(); if (remain < length + 2) { // 如果buffer中只有部分数据 return false; } // 读取所有data byte[] byteArray = new byte[length]; buffer.readBytes(byteArray); buffer.skipBytes(2);// skip \r\n command.getValue().setValueBytes(byteArray); return true; } protected void parseHead(byte[] headBytes, GetCommand command) { int start = 0; if (headBytes[start] == 'V' && headBytes[start + 1] == 'A') {// VALUE parseValue(headBytes, command); return; } else if (headBytes[start] == 'E' && headBytes[start + 1] == 'N' && headBytes[start + 2] == 'D') {// END command.setSuccess(true); command.setValue(nullValue); return; } else { // success means this command processing success. command.setSuccess(true); generateErrorMessage(command, headBytes); return; } } protected void parseValue(byte[] headBytes, GetCommand command) { int startPos = 6;// skip "VALUE " int[] pos = { startPos }; // skip key skipNextField(headBytes, pos); Value value = new ValueImpl(null, 0); command.setValue(value); value.setFlag(Short.parseShort(parseNextField(headBytes, pos))); // skip vnode skipNextField(headBytes, pos); // parse time stamp String timeStamp = parseNextField(headBytes, pos); value.setTimestamp(Long.parseLong(timeStamp)); // parse value bytes. String v = parseNextField(headBytes, pos); command.setValueBytes(Integer.parseInt(v)); } private static final Value nullValue = new NullValueImpl(); }