package com.alibaba.doris.client.net.protocol.text;
import org.jboss.netty.buffer.ChannelBuffer;
import com.alibaba.doris.client.net.command.BaseCommand;
import com.alibaba.doris.client.net.command.ErrorType;
import com.alibaba.doris.client.net.protocol.ProtocolParser;
import com.alibaba.doris.common.data.util.ByteUtils;
/**
* @author ajun Email:jack.yuj@alibaba-inc.com
*/
public abstract class TextProtocolParser implements ProtocolParser {
public static final byte[] CRLF = { '\r', '\n' };
public static final byte[] SPLID = { ' ' };
public static final byte[] SET = { 's', 'e', 't' };
public static final byte[] CAS = { 'c', 'a', 's' };
public static final byte[] CAD = { 'c', 'a', 'd' };
public static final byte[] GET = { 'g', 'e', 't' };
public static final byte[] GETS = { 'g', 'e', 't', 's' };
public static final byte[] CHECK = { 'c', 'h', 'e', 'c', 'k' };
public static final byte SPACE = ' ';
public static final byte[] DELETE = { 'd', 'e', 'l', 'e', 't', 'e' };
public static final byte[] NOREPLY = { 'n', 'o', 'r', 'e', 'p', 'l', 'y' };
public static final byte[] STATS = { 's', 't', 'a', 't', 's' };
public static final byte[] VERSION = { 'v', 'e', 'r', 's', 'i', 'o', 'n' };
public static final byte[] STORED = { 'S', 'T', 'O', 'R', 'E', 'D' };
public static final byte[] DELETED = { 'D', 'E', 'L', 'E', 'T', 'E', 'D' };
public static final byte[] NOT_STORED = { 'N', 'O', 'T', '_', 'S', 'T', 'O', 'R', 'E', 'D' };
public static final byte[] NOT_FOUND = { 'N', 'O', 'T', '_', 'F', 'O', 'U', 'N', 'D' };
public static final byte[] DELETE_FAILED = { 'D', 'E', 'L', 'E', 'T', 'E', '_', 'F', 'A', 'I', 'L', 'E', 'D' };
public static final byte[] ERROR = { 'E', 'R', 'R', 'O', 'R' };
public static final byte[] CLIENT_ERROR = { 'C', 'L', 'I', 'E', 'N', 'T', '_', 'E', 'R', 'R', 'O', 'R' };
public static final byte[] SERVER_ERROR = { 'S', 'E', 'R', 'V', 'E', 'R', '_', 'E', 'R', 'R', 'O', 'R' };
public static final byte[] VERSION_OUT_OF_DATE = { 'V', 'E', 'R', 'S', 'I', 'O', 'N', '_', 'O', 'U', 'T', '_', 'O',
'F', '_', 'D', 'A', 'T', 'E' };
public static final byte[] VALUE = { 'V', 'A', 'L', 'U', 'E' };
protected void assemableCommandData(ChannelBuffer buffer, byte[]... args) {
boolean isFirst = true;
for (byte[] o : args) {
if (isFirst) {
isFirst = false;
} else {
buffer.writeBytes(SPLID);
}
buffer.writeBytes(o);
}
buffer.writeBytes(CRLF);
}
public byte[] readLine(ChannelBuffer buf) {
byte b = 0;
int pos;
int startPos = pos = 0;
int limit = buf.readableBytes();
boolean eol = false;
buf.markReaderIndex();
while (pos < limit) {
b = buf.readByte();
pos++;
if (b == CRLF[0]) {
eol = true;
} else {
if (eol) {
if (b == CRLF[1]) {
eol = false;
byte[] byteArray = new byte[pos - startPos];
buf.resetReaderIndex();
buf.readBytes(byteArray);
return byteArray;
}
eol = false;
}
}
}
buf.resetReaderIndex();
return null;
}
protected String parseNextField(byte[] line, int[] startPos) {
int pos = startPos[0];
while (line[pos] != SPACE && line[pos] != CRLF[0] && pos < line.length) {
pos++;
}
// skip ' '
pos++;
String value = ByteUtils.byteToString(line, startPos[0], (pos - startPos[0] - 1));
startPos[0] = pos;
return value;
}
protected void skipNextField(byte[] line, int[] startPos) {
int pos = startPos[0];
while (line[pos] != SPACE && line[pos] != CRLF[0]) {
pos++;
}
// skip ' '
pos++;
startPos[0] = pos;
return;
}
protected void generateErrorMessage(BaseCommand<?> command, byte[] messageBytes) {
if ((messageBytes[0] == ERROR[0]) && (messageBytes[4] == ERROR[4])) {
int start = ERROR.length + 1;
command.setErrorMessage(getErrorMessage(messageBytes, start));
command.setErrorType(ErrorType.UNKNOWN);
return;
}
if (messageBytes[0] == VERSION_OUT_OF_DATE[0] && messageBytes[4] == VERSION_OUT_OF_DATE[4]) {
int start = VERSION_OUT_OF_DATE.length + 1;
command.setErrorMessage(getErrorMessage(messageBytes, start));
command.setErrorType(ErrorType.VERSION_OUT_OF_DATE);
return;
}
if (messageBytes[0] == CLIENT_ERROR[0] && messageBytes[4] == CLIENT_ERROR[4]) {
// read error message
int start = CLIENT_ERROR.length + 1;
command.setErrorMessage(getErrorMessage(messageBytes, start));
command.setErrorType(ErrorType.CLIENT_ERROR);
return;
}
if (messageBytes[0] == SERVER_ERROR[0] && messageBytes[4] == SERVER_ERROR[4]) {
// read error message
int start = SERVER_ERROR.length + 1;
command.setErrorMessage(getErrorMessage(messageBytes, start));
command.setErrorType(ErrorType.SERVER_ERROR);
return;
}
command.setErrorMessage("Unknown exception! " + ByteUtils.byteToString(messageBytes));
command.setErrorType(ErrorType.UNKNOWN);
}
protected String getErrorMessage(byte[] messageBytes, int start) {
// skip \r\n
int len = messageBytes.length - start - 2;
if (len > 0) {
// read error message
return ByteUtils.byteToString(messageBytes, start, len);
}
return "";
}
/**
* 判断当前流是否是命令结束标记。
*
* @param byteArray
* @return
*/
protected boolean checkIsEndFlag(byte[] lineBytes) {
int start = 0;
if (lineBytes[start] == 'E' && lineBytes[start + 1] == 'N' /* && lineBytes[start + 2] == 'D' */) {
return true;
}
return false;
}
}