/*
* Copyright 1999-2012 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package fm.liu.timo.mysql.handler;
import java.util.ArrayList;
import java.util.List;
import fm.liu.timo.mysql.ByteUtil;
import fm.liu.timo.mysql.connection.MySQLConnection;
import fm.liu.timo.mysql.packet.EOFPacket;
import fm.liu.timo.mysql.packet.ErrorPacket;
import fm.liu.timo.mysql.packet.OkPacket;
import fm.liu.timo.net.connection.AbstractConnection.State;
import fm.liu.timo.net.handler.BackendHandler;
import fm.liu.timo.server.session.handler.ResultHandler;
/**
* life cycle: from connection establish to close <br/>
*
* @author xianmao.hexm 2012-4-12
*/
public class ConnectorHandler extends BackendHandler {
private static final int RESULT_STATUS_INIT = 0;
private static final int RESULT_STATUS_HEADER = 1;
private static final int RESULT_STATUS_FIELD_EOF = 2;
private final MySQLConnection con;
private volatile int resultStatus;
private volatile byte[] header;
private volatile List<byte[]> fields;
public ConnectorHandler(MySQLConnection source) {
this.con = source;
this.resultStatus = RESULT_STATUS_INIT;
}
public void connectionError(Throwable e) {
dataQueue.clear();
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.close("connection error");
}
}
public MySQLConnection getSource() {
return con;
}
@Override
public void handle(byte[] data) {
offerData(data, con.getProcessor().getExecutor());
}
@Override
protected void offerDataError() {
dataQueue.clear();
resultStatus = RESULT_STATUS_INIT;
throw new RuntimeException("offer data error!");
}
@Override
protected void handleData(byte[] data) {
switch (resultStatus) {
case RESULT_STATUS_INIT:
switch (data[4]) {
case OkPacket.FIELD_COUNT:
handleOkPacket(data);
break;
case ErrorPacket.FIELD_COUNT:
handleErrorPacket(data);
break;
default:
resultStatus = RESULT_STATUS_HEADER;
header = data;
fields = new ArrayList<byte[]>((int) ByteUtil.readLength(data, 4));
}
break;
case RESULT_STATUS_HEADER:
switch (data[4]) {
case ErrorPacket.FIELD_COUNT:
resultStatus = RESULT_STATUS_INIT;
handleErrorPacket(data);
break;
case EOFPacket.FIELD_COUNT:
resultStatus = RESULT_STATUS_FIELD_EOF;
handleFieldEofPacket(data);
break;
default:
fields.add(data);
}
break;
case RESULT_STATUS_FIELD_EOF:
switch (data[4]) {
case ErrorPacket.FIELD_COUNT:
resultStatus = RESULT_STATUS_INIT;
handleErrorPacket(data);
break;
case EOFPacket.FIELD_COUNT:
resultStatus = RESULT_STATUS_INIT;
handleRowEofPacket(data);
break;
default:
handleRowPacket(data);
}
break;
default:
throw new RuntimeException("unknown status!");
}
}
@Override
protected void handleDataError(Throwable t) {
dataQueue.clear();
resultStatus = RESULT_STATUS_INIT;
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.close("handle data error");
}
}
/**
* OK数据包处理
*/
private void handleOkPacket(byte[] data) {
con.setState(State.borrowed);
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.ok(data, con);
}
}
/**
* ERROR数据包处理
*/
private void handleErrorPacket(byte[] data) {
con.setState(State.borrowed);
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.error(data, con);
}
}
/**
* 字段数据包结束处理
*/
private void handleFieldEofPacket(byte[] data) {
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.field(header, fields, data, con);
}
}
/**
* 行数据包处理
*/
private void handleRowPacket(byte[] data) {
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.row(data, con);
}
}
/**
* 行数据包结束处理
*/
private void handleRowEofPacket(byte[] data) {
con.setState(State.borrowed);
ResultHandler handler = con.getResultHandler();
if (handler != null) {
handler.eof(data, con);
}
}
}