/*
* This program is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.meidusa.amoeba.mysql.handler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.meidusa.amoeba.mysql.net.CommandInfo;
import com.meidusa.amoeba.mysql.net.CommandListener;
import com.meidusa.amoeba.mysql.net.MysqlClientConnection;
import com.meidusa.amoeba.mysql.net.MysqlConnection;
import com.meidusa.amoeba.mysql.net.MysqlServerConnection;
import com.meidusa.amoeba.mysql.net.packet.EOFPacket;
import com.meidusa.amoeba.mysql.net.packet.ErrorPacket;
import com.meidusa.amoeba.mysql.net.packet.MysqlPacketBuffer;
import com.meidusa.amoeba.mysql.net.packet.OkPacket;
import com.meidusa.amoeba.mysql.net.packet.QueryCommandPacket;
import com.meidusa.amoeba.net.Connection;
import com.meidusa.amoeba.net.MessageHandler;
import com.meidusa.amoeba.net.Sessionable;
import com.meidusa.amoeba.net.packet.AbstractPacketBuffer;
import com.meidusa.amoeba.net.packet.Packet;
import com.meidusa.amoeba.net.packet.PacketBuffer;
import com.meidusa.amoeba.net.poolable.ObjectPool;
import com.meidusa.amoeba.net.poolable.PoolableObject;
import com.meidusa.amoeba.util.Reporter;
import com.meidusa.amoeba.util.StringUtil;
/**
*
* @author <a href=mailto:piratebase@sina.com>Struct chen</a>
*
*/
public abstract class CommandMessageHandler implements MessageHandler,Sessionable,Reporter.SubReporter {
private static Logger logger = Logger.getLogger(CommandMessageHandler.class);
/**
* ��ʾ���������ص����ݰ�����ʾ��ǰ�Ự״̬
* @author <a href=mailto:piratebase@sina.com>Struct chen</a>
*
*/
static class SessionStatus{
public static final int QUERY = 1;
public static final int RESULT_HEAD = 2;
public static final int EOF_FIELDS = 4;
public static final int EOF_ROWS = 8;
public static final int OK = 16;
public static final int ERROR = 32;
public static final int COMPLETED = 64;
}
static enum CommandStatus{
ConnectionNotComplete,ConnectionCompleted,AllCompleted
}
/**
* ������������ӵ�״̬��������ǰ�����״̬,��ǰ���ӵ����ݰ�
* @author <a href=mailto:piratebase@sina.com>Struct chen</a>
*
*/
static abstract class ConnectionStatuts{
protected Connection conn;
public ConnectionStatuts(Connection conn){
this.conn = conn;
}
int statusCode;
int packetIndex;
List<byte[]> buffers;
protected byte commandType;
public void clearBuffer(){
if(buffers != null){
buffers.clear();
}
}
public void setCommandType(byte commandType){
this.commandType = commandType;
statusCode = 0;
packetIndex = 0;
}
/**
* �жϴӷ������˷��ص����ݰ��Ƿ��ʾ��ǰ����Ľ�����
* @param buffer
* @return
*/
public boolean isCompleted(byte[] buffer) {
if(this.commandType == QueryCommandPacket.COM_INIT_DB){
boolean isCompleted = false;
if(MysqlPacketBuffer.isErrorPacket(buffer)){
statusCode |= SessionStatus.ERROR;
statusCode |= SessionStatus.COMPLETED;
isCompleted = true;
}else if(MysqlPacketBuffer.isOkPacket(buffer)){
statusCode |= SessionStatus.OK;
statusCode |= SessionStatus.COMPLETED;
isCompleted = true;
}
return isCompleted;
}else{
return false;
}
}
}
protected static class CommandQueue{
protected List<CommandInfo> sessionInitQueryQueue; //���еĴӿͻ��˷������� command ����
protected CommandInfo currentCommand;//��ǰ��query
private final Lock lock = new ReentrantLock(false);
protected Map<MysqlServerConnection,ConnectionStatuts> connStatusMap = new HashMap<MysqlServerConnection,ConnectionStatuts>();
private boolean mainCommandExecuted;
private MysqlClientConnection source;
public CommandQueue(MysqlClientConnection source){
this.source = source;
}
public boolean isMultiple(){
return connStatusMap.size()>1;
}
public void clearAllBuffer(){
Collection<ConnectionStatuts> collection = connStatusMap.values();
for(ConnectionStatuts status : collection){
status.clearBuffer();
}
}
/**
* ������һ������������false����ʾ������û�������ˡ�
*
* @return
*/
private boolean tryNextCommandTuple(){
if(sessionInitQueryQueue == null){
return false;
}else{
if(sessionInitQueryQueue.size()>0){
currentCommand = sessionInitQueryQueue.get(0);
if(logger.isDebugEnabled()){
QueryCommandPacket command = new QueryCommandPacket();
command.init(currentCommand.getBuffer(),source);
logger.debug(command);
}
return true;
}
return false;
}
}
/**
* �жϷ��ص������Ƿ��ǵ�ǰ����Ľ�������
* ��ǰȫ�����Ӷ�ȫ�������Ժ����ʾ��ǰ������ȫ������
* @param conn
* @param buffer
* @return
*/
protected CommandStatus checkResponseCompleted(Connection conn,byte[] buffer){
boolean isCompleted = false;
ConnectionStatuts connStatus = connStatusMap.get(conn);
if(connStatus == null){
logger.error("connection Status not Found, byffer="+StringUtil.dumpAsHex(buffer, buffer.length));
}
isCompleted = connStatus.isCompleted(buffer);
connStatus.packetIndex ++;
/**
* ����Ƕ�����ӵģ���Ҫ�����ݻ����������ȴ�����ȫ������Ժ����ݽ�����װ��Ȼ���͵��ͻ���
* {@link #CommandMessageHandler.mergeMessageToClient}
*/
if(connStatus.buffers == null){
connStatus.buffers = new ArrayList<byte[]>();
}
connStatus.buffers.add(buffer);
if(isCompleted){
lock.lock();
try{
if(currentCommand.getCompletedCount().incrementAndGet() == connStatusMap.size()){
if(logger.isDebugEnabled()){
Packet packet = null;
if(MysqlPacketBuffer.isErrorPacket(buffer)){
packet = new ErrorPacket();
}else if(MysqlPacketBuffer.isEofPacket(buffer)){
packet = new EOFPacket();
}else if(MysqlPacketBuffer.isOkPacket(buffer)){
packet = new OkPacket();
}
packet.init(buffer,conn);
logger.debug("returned Packet:"+packet);
}
return CommandStatus.AllCompleted;
}else{
return CommandStatus.ConnectionCompleted;
}
}finally{
lock.unlock();
}
}else{
return CommandStatus.ConnectionNotComplete;
}
}
/**
* �Ƿ�append �ɹ�������ɹ����ʾ��ǰ�����ѻ�������Ҫ��������֤���������ѭ��
* ���������û�жѻ��������false.
* ����true�� ���ʾ��ֱ�ӷ�������
* @param commandInfo
* @param force ǿ��append �������Ϊtrue
* @return
*/
public synchronized boolean appendCommand(CommandInfo commandInfo,boolean force){
if(force){
if(sessionInitQueryQueue == null){
sessionInitQueryQueue = Collections.synchronizedList(new ArrayList<CommandInfo>());
}
if(!sessionInitQueryQueue.contains(commandInfo)){
sessionInitQueryQueue.add(commandInfo);
}
return true;
}else{
if(sessionInitQueryQueue == null){
return false;
}else{
if(sessionInitQueryQueue.size() ==0){
return false;
}
if(!sessionInitQueryQueue.contains(commandInfo)){
sessionInitQueryQueue.add(commandInfo);
}
return true;
}
}
}
}
protected MysqlClientConnection source;
private boolean completed;
private long createTime;
private long timeout;
private long endTime;
private boolean ended = false;
protected CommandQueue commandQueue;
private ObjectPool[] pools;
private CommandInfo info = new CommandInfo();
protected byte commandType;
protected Map<Connection,MessageHandler> handlerMap = new HashMap<Connection,MessageHandler>();
private final Lock lock = new ReentrantLock(false);
private PacketBuffer buffer = new AbstractPacketBuffer(1400);
public CommandMessageHandler(final MysqlClientConnection source,byte[] query,ObjectPool[] pools,long timeout){
handlerMap.put(source, source.getMessageHandler());
source.setMessageHandler(this);
commandQueue = new CommandQueue(source);
QueryCommandPacket command = new QueryCommandPacket();
command.init(query,source);
this.pools = pools;
info.setBuffer(query);
info.setMain(true);
this.source = source;
this.createTime = System.currentTimeMillis();
this.timeout = timeout;
}
/**
* �жϱ�handled��Connection ��Ϣ�����Ƿ����
* @return
*/
public boolean isCompleted(){
return completed;
}
/**
* ��Ҫ��Ϊ�˷�������� �� �ͻ������ӵĻ���һ�£����磬��ǰ��schema ��charset�ȣ�
*
* �ڷ���������֮ǰ��Ԥ����Ҫ����һЩ������������sourceConnection��destConnection ��ǰ��database��һ�£���Ҫ����init_db Command
* Ϊ�˼��ٸ��Ӷȣ�ֻҪһ��Connection��Ҫ���������ô�������Ӷ����뷢��һ����ͬ�����
*
* @param sourceMysql
* @param destMysqlConn
*/
//TODO ��Ҫ�����Ż�
protected void appendPreMainCommand(){
Set<MysqlServerConnection> connSet = commandQueue.connStatusMap.keySet();
final MysqlConnection sourceMysql =(MysqlConnection) source;
for(Connection destConn : connSet){
MysqlConnection destMysqlConn = (MysqlConnection)destConn;
if(!StringUtil.equalsIgnoreCase(sourceMysql.getSchema(), destMysqlConn.getSchema())){
if(sourceMysql.getSchema() != null){
QueryCommandPacket selectDBCommand = new QueryCommandPacket();
selectDBCommand.query = sourceMysql.getSchema();
selectDBCommand.command = QueryCommandPacket.COM_INIT_DB;
byte[] buffer = selectDBCommand.toByteBuffer(destMysqlConn).array();
CommandInfo info = new CommandInfo();
info.setBuffer(buffer);
info.setMain(false);
info.setRunnable(new Runnable(){
public void run() {
Set<MysqlServerConnection> connSet = commandQueue.connStatusMap.keySet();
for(Connection conn : connSet){
((MysqlConnection)conn).setSchema(sourceMysql.getSchema());
}
}
});
commandQueue.appendCommand(info,true);
}
}
if(sourceMysql.getCharset()!= null &&
!StringUtil.equalsIgnoreCase(sourceMysql.getCharset(),destMysqlConn.getCharset())){
QueryCommandPacket charsetCommand = new QueryCommandPacket();
charsetCommand.query = "set names " + sourceMysql.getCharset();
charsetCommand.command = QueryCommandPacket.COM_QUERY;
byte[] buffer = charsetCommand.toByteBuffer(sourceMysql).array();
CommandInfo info = new CommandInfo();
info.setBuffer(buffer);
info.setMain(false);
info.setRunnable(new Runnable(){
public void run() {
Set<MysqlServerConnection> connSet = commandQueue.connStatusMap.keySet();
for(Connection conn : connSet){
((MysqlConnection)conn).setCharset(sourceMysql.getCharset());
}
}
});
commandQueue.appendCommand(info,true);
}
if(sourceMysql.isAutoCommit() != destMysqlConn.isAutoCommit()){
QueryCommandPacket charsetCommand = new QueryCommandPacket();
charsetCommand.query = "set autocommit = " + (sourceMysql.isAutoCommit()?1:0);
charsetCommand.command = QueryCommandPacket.COM_QUERY;
byte[] buffer = charsetCommand.toByteBuffer(sourceMysql).array();
CommandInfo info = new CommandInfo();
info.setBuffer(buffer);
info.setMain(false);
info.setRunnable(new Runnable(){
public void run() {
Set<MysqlServerConnection> connSet = commandQueue.connStatusMap.keySet();
for(Connection conn : connSet){
((MysqlConnection)conn).setAutoCommit(sourceMysql.isAutoCommit());
}
}
});
commandQueue.appendCommand(info,true);
}
}
}
protected void appendAfterMainCommand(){
}
/**
* �����ӿ�ʼһ�������ʱ��
* @param conn
*/
protected void startConnectionCommand(Connection conn,CommandInfo currentCommand){
if(conn instanceof CommandListener){
CommandListener listener = (CommandListener)conn;
listener.startCommand(commandQueue.currentCommand);
}
}
/**
* ���������һ�������ʱ��ִ�У�ֻ����������Լ����������������ӡ�
* @param conn
*/
protected void finishedConnectionCommand(Connection conn,CommandInfo currentCommand){
if(conn instanceof CommandListener){
CommandListener listener = (CommandListener) conn;
listener.finishedCommand(this.commandQueue.currentCommand);
}
}
public void handleMessage(Connection fromConn, byte[] message) {
/*if(ended){
logger.error("ended session handler handle message:\n"+StringUtil.dumpAsHex(message, message.length));
return;
}*/
if(fromConn == source){
CommandInfo info = new CommandInfo();
info.setBuffer(message);
info.setMain(true);
if(!commandQueue.appendCommand(info,false)){
dispatchMessageFrom(source,message);
}
}else{
if(logger.isDebugEnabled()){
if(MysqlPacketBuffer.isErrorPacket(message)){
logger.error("connection="+fromConn.hashCode()+",error packet:\n"+StringUtil.dumpAsHex(message, message.length));
}
}
//�ж������Ƿ������
CommandStatus commStatus = commandQueue.checkResponseCompleted(fromConn, message);
if(CommandStatus.AllCompleted == commStatus || CommandStatus.ConnectionCompleted == commStatus){
finishedConnectionCommand(fromConn,commandQueue.currentCommand);
lock.lock();
try{
if(this.ended){
releaseConnection(fromConn);
}
}finally{
lock.unlock();
}
}
if(CommandStatus.AllCompleted == commStatus){
try{
if(commandQueue.currentCommand.isMain()){
commandQueue.mainCommandExecuted = true;
releaseConnection(source);
}
/**
* ����ǿͻ��������������:
* 1�������Ƕ�̨server�ģ���Ҫ���кϲ�����
* 2����̨serverֱ��д�����ͻ���
*/
if(commandQueue.currentCommand.isMain()){
if(commandQueue.isMultiple()){
List<byte[]> list = this.mergeMessages();
if(list != null){
for(byte[] buffer : list){
dispatchMessageFrom(fromConn,buffer);
}
}
}else{
dispatchMessageFrom(fromConn,message);
}
}else{
//����������Ժس�����Ϣ���������ǰ��session
Collection<ConnectionStatuts> connectionStatutsSet = commandQueue.connStatusMap.values();
for(ConnectionStatuts connStatus : connectionStatutsSet){
//���Ƿ�ÿ�����������ص����ݰ���û���쳣��Ϣ��
if((connStatus.statusCode & SessionStatus.ERROR) >0){
this.commandQueue.currentCommand.setStatusCode(connStatus.statusCode);
byte[] errorBuffer = connStatus.buffers.get(connStatus.buffers.size()-1);
if(!commandQueue.mainCommandExecuted){
dispatchMessageFrom(connStatus.conn,errorBuffer);
if(source.isAutoCommit()){
this.endSession();
}
}else{
if(logger.isDebugEnabled()){
byte[] commandBuffer = commandQueue.currentCommand.getBuffer();
StringBuffer buffer = new StringBuffer();
buffer.append("Current Command Execute Error:\n");
buffer.append(StringUtil.dumpAsHex(commandBuffer,commandBuffer.length));
buffer.append("\n error Packet:\n");
buffer.append(StringUtil.dumpAsHex(errorBuffer,errorBuffer.length));
logger.debug(buffer.toString());
}
}
return;
}
}
}
}finally{
afterCommandCompleted(commandQueue.currentCommand);
}
}else{
if(commandQueue.currentCommand.isMain()){
if(!commandQueue.isMultiple()){
dispatchMessageFrom(fromConn,message);
}
}
}
}
}
/**
* ��һ�����������ʱ������������ݰ������ҳ��Է�����һ��command
* ���������û������������ǰ�ػ�
* @param oldCommand ��ǰ��command
*/
protected void afterCommandCompleted(CommandInfo oldCommand){
if(oldCommand.getRunnable()!= null){
oldCommand.getRunnable().run();
}
commandQueue.clearAllBuffer();
//��һ����������һ�����ݰ������ǰ������Ӷ�����ɾ����
commandQueue.sessionInitQueryQueue.remove(0);
if(!ended){
startNextCommand();
}
}
//�ж��Ƿ���Ҫ����������һ���ͻ�������
//������һ������
protected synchronized void startNextCommand(){
if(commandQueue.currentCommand != null && (commandQueue.currentCommand.getStatusCode() & SessionStatus.ERROR) >0){
if(source.isAutoCommit()){
this.endSession();
}
return;
}
if(!this.ended && commandQueue.tryNextCommandTuple()){
commandType = commandQueue.currentCommand.getBuffer()[4];
Collection<ConnectionStatuts> connSet = commandQueue.connStatusMap.values();
boolean commandCompleted = commandQueue.currentCommand.getCompletedCount().get() == commandQueue.connStatusMap.size();
if(!commandCompleted){
for(ConnectionStatuts status : connSet){
status.setCommandType(commandType);
startConnectionCommand(status.conn,commandQueue.currentCommand);
}
}
dispatchMessageFrom(source,commandQueue.currentCommand.getBuffer());
if(commandCompleted){
afterCommandCompleted(commandQueue.currentCommand);
}
}else{
if(source.isAutoCommit()){
this.endSession();
}
}
}
/**
* �κ���handler������Ҫ���͵�Ŀ�����ӵ����ݰ��������ø÷������ͳ�ȥ��
* �ӷ������˷���������Ϣ���ͻ��ˣ����ߴӿͻ��˷����������mysql server��
*
* �����Ҫ���͵���Ϣ��2�֣�
* 1���ӿͻ��˷���������Ϣ
* 2��reponse��ǰ����Ҫ����ǿͻ��˷���������������Ǹ�proxy�ڲ���������������ݰ�
* ����2�����ݰ�ͨ��dispatchMessage �������ͳ�ȥ�ġ�
* ���ڲ��������������ݰ������� afterCommandCompleted()֮�� ����ConnectionStatus.buffers�б��档
* commandQueue.clearAllBuffer() �Ժ�buffers �������
*
* @param fromServer �Ƿ��Ǵ�mysql server �˷�������
* @param message ��Ϣ����
*/
protected void dispatchMessageFrom(Connection fromConn,byte[] message){
if(fromConn != source){
dispatchMessageTo(source,message);
}else{
Collection<MysqlServerConnection> connSet = commandQueue.connStatusMap.keySet();
for(Connection conn : connSet){
dispatchMessageTo(conn,message);
}
}
}
/**
* ���������һЩ������ƣ�����С���ݰ�Ƶ������ ϵͳwrite, CommandMessageHandler��������������ͨ���÷����������ݰ�
* @param toConn
* @param message
*/
protected void dispatchMessageTo(Connection toConn,byte[] message){
if(toConn == source){
if(message != null){
appendBufferToWrite(message,buffer,toConn,false);
}else{
appendBufferToWrite(message,buffer,toConn,true);
}
}else{
toConn.postMessage(message);
}
}
private boolean appendBufferToWrite(byte[] byts,PacketBuffer buffer,Connection conn,boolean writeNow){
if(byts == null){
if(buffer.getPosition()>0){
conn.postMessage(buffer.toByteBuffer());
buffer.reset();
}
return true;
}else{
if(writeNow || buffer.remaining() < byts.length){
if(buffer.getPosition()>0){
buffer.writeBytes(byts);
conn.postMessage(buffer.toByteBuffer());
buffer.reset();
}else{
conn.postMessage(byts);
}
return true;
}else{
buffer.writeBytes(byts);
return true;
}
}
}
protected void releaseConnection(Connection conn){
lock.lock();
try{
MessageHandler handler = handlerMap.remove(conn);
if(handler != null){
conn.setMessageHandler(handler);
}
if(conn instanceof MysqlServerConnection){
PoolableObject pooledObject = (PoolableObject)conn;
if(pooledObject.getObjectPool() != null){
try {
pooledObject.getObjectPool().returnObject(conn);
if(logger.isDebugEnabled()){
logger.debug("connection:"+conn+" return to pool");
}
} catch (Exception e) {
}
}
}
}finally{
lock.unlock();
}
}
/**
* �رո�messageHandler ���һָ��������messageHandler��handle��Connection
*/
protected void releaseAllCompletedConnection(){
lock.lock();
try{
Set<Map.Entry<Connection,MessageHandler>> handlerSet = handlerMap.entrySet();
for(Map.Entry<Connection,MessageHandler> entry:handlerSet){
MessageHandler handler = entry.getValue();
Connection connection = entry.getKey();
ConnectionStatuts status = this.commandQueue.connStatusMap.get(connection);
if(this.commandQueue.currentCommand == null || status != null && (status.statusCode & SessionStatus.COMPLETED)>0){
connection.setMessageHandler(handler);
if(!connection.isClosed()){
if(connection instanceof MysqlServerConnection){
PoolableObject pooledObject = (PoolableObject)connection;
if(pooledObject.getObjectPool() != null){
try {
pooledObject.getObjectPool().returnObject(connection);
if(logger.isDebugEnabled()){
logger.debug("connection:"+connection+" return to pool");
}
} catch (Exception e) {
}
}
}
}
}
}
}finally{
lock.unlock();
}
}
/**
* �ϲ������˵���Ϣ�����͵��ͻ���
* ֻ���ڶ����ӵ��������Ҫ�������ݰ��ۺϣ��ۺ��Ժ���һ�����ݰ�ͨ�� {@link #dispatchMessageFrom(Connection, byte[])}�������ͳ�ȥ,
* һ��һ������ֱ��ͨ��{@link #dispatchMessageFrom(Connection, byte[])} ���� ֱ�ӷ��ͳ�ȥ,������Ҫmerge��
* @return
*/
protected List<byte[]> mergeMessages(){
Collection<ConnectionStatuts> connectionStatutsSet = commandQueue.connStatusMap.values();
boolean isSelectQuery = true;
List<byte[]> buffers = null;
List<byte[]> returnList = new ArrayList<byte[]>();
for(ConnectionStatuts connStatus : connectionStatutsSet){
//���Ƿ�ÿ�����������ص����ݰ���û���쳣��Ϣ��
byte[] buffer = connStatus.buffers.get(connStatus.buffers.size()-1);
buffers = connStatus.buffers;
if((connStatus.statusCode & SessionStatus.ERROR) >0){
return buffers;
}
if(isSelectQuery){
isSelectQuery =isSelectQuery && MysqlPacketBuffer.isEofPacket(buffer);
}
}
if(isSelectQuery){
//��ǰ��packetId
byte paketId = 0;
//����field��Ϣ
for(byte[] buffer : buffers){
if(MysqlPacketBuffer.isEofPacket(buffer)){
returnList.add(buffer);
paketId = buffer[3];
break;
}else{
returnList.add(buffer);
paketId = buffer[3];
}
}
paketId += 1;
//����rows���ݰ�
for(ConnectionStatuts connStatus : connectionStatutsSet){
boolean rowStart = false;;
for(byte[] buffer : connStatus.buffers){
if(!rowStart){
if(MysqlPacketBuffer.isEofPacket(buffer)){
rowStart = true;
}else{
continue;
}
}else{
if(!MysqlPacketBuffer.isEofPacket(buffer)){
buffer[3] = paketId;
paketId += 1;
returnList.add(buffer);
}
}
}
}
byte[] eofBuffer = buffers.get(buffers.size()-1);
eofBuffer[3] = paketId;
returnList.add(eofBuffer);
}else{
OkPacket ok = new OkPacket();
StringBuffer strbuffer = new StringBuffer();
for(ConnectionStatuts connStatus : connectionStatutsSet){
byte[] buffer = connStatus.buffers.get(connStatus.buffers.size()-1);
OkPacket connOK = new OkPacket();
connOK.init(buffer,connStatus.conn);
ok.affectedRows +=connOK.affectedRows;
ok.insertId =connOK.insertId;
ok.packetId = 1;
strbuffer.append(connOK.message);
ok.warningCount +=connOK.warningCount;
}
ok.message = strbuffer.toString();
returnList.add(ok.toByteBuffer(source).array());
}
return returnList;
}
protected abstract ConnectionStatuts newConnectionStatuts(Connection conn);
public synchronized void startSession() throws Exception {
if(logger.isInfoEnabled()){
logger.info(this+" session start");
}
for(ObjectPool pool:pools){
MysqlServerConnection conn;
conn = (MysqlServerConnection)pool.borrowObject();
handlerMap.put(conn, conn.getMessageHandler());
conn.setMessageHandler(this);
commandQueue.connStatusMap.put(conn, newConnectionStatuts(conn));
}
appendPreMainCommand();
this.commandQueue.appendCommand(info, true);
appendAfterMainCommand();
startNextCommand();
}
public boolean checkIdle(long now) {
if(timeout >0){
return (now - createTime)>timeout;
}else{
if(ended){
/**
* �����session�Ѿ���������ʱ���serverConnection�˻��ڵȴ��������ݷ��ʡ����ҳ���15s,����Ҫ�����еĻỰ
* �������ڸ���ԭ����ɷ�������û�з������ݻ����Ѿ������ĻỰ��ServerConnection������Pool�С�
*/
return (now - endTime)>15000;
}
return false;
}
}
public void endSession() {
lock.lock();
try{
if(!ended){
endTime = System.currentTimeMillis();
ended = true;
this.releaseAllCompletedConnection();
if(!this.commandQueue.mainCommandExecuted){
ErrorPacket error = new ErrorPacket();
error.errno = 10000;
error.packetId = 2;
error.serverErrorMessage = "session was killed!!";
this.dispatchMessageTo(source, error.toByteBuffer(source).array());
logger.warn("session was killed!!",new Exception());
source.postClose(null);
}else{
if(logger.isInfoEnabled()){
logger.info(this+" session ended.");
}
}
this.dispatchMessageTo(this.source, null);
}
}finally{
lock.unlock();
}
}
public boolean isEnded() {
lock.lock();
try{
return this.ended;
}finally{
lock.unlock();
}
}
public void appendReport(StringBuilder buffer, long now, long sinceLast,boolean reset,Level level) {
buffer.append(" -- MessageHandler:").append("multiple Size:").append(commandQueue.connStatusMap.size());
if(commandQueue.currentCommand != null){
buffer.append(",currentCommand completedCount:");
buffer.append(commandQueue.currentCommand.getCompletedCount()).append("\n");
}else{
buffer.append("\n");
}
}
}