/** * <pre> * 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. * </pre> */ package com.meidusa.amoeba.mysql.handler; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import com.meidusa.amoeba.context.ProxyRuntimeContext; import com.meidusa.amoeba.mysql.net.MysqlClientConnection; import com.meidusa.amoeba.mysql.net.packet.ErrorPacket; import com.meidusa.amoeba.mysql.net.packet.ExecutePacket; import com.meidusa.amoeba.mysql.net.packet.LongDataPacket; 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.poolable.ObjectPool; import com.meidusa.amoeba.route.QueryRouter; /** * handler * * @author <a href=mailto:piratebase@sina.com>Struct chen</a> */ public class MySqlCommandDispatcher implements MessageHandler { protected static Logger logger = Logger.getLogger(MySqlCommandDispatcher.class); private static long timeout = -1; private static byte[] STATIC_OK_BUFFER; static { OkPacket ok = new OkPacket(); ok.affectedRows = 0; ok.insertId = 0; ok.packetId = 1; ok.serverStatus = 2; STATIC_OK_BUFFER = ok.toByteBuffer(null).array(); } public void handleMessage(Connection connection, byte[] message) { MysqlClientConnection conn = (MysqlClientConnection) connection; QueryCommandPacket command = new QueryCommandPacket(); command.init(message, connection); try { if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_QUIT) || MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_STMT_CLOSE)) { if (logger.isDebugEnabled()) { logger.debug(command); } } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_PING)) { conn.postMessage(STATIC_OK_BUFFER); } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_QUERY)) { QueryRouter router = ProxyRuntimeContext.getInstance().getQueryRouter(); ObjectPool[] pools = router.doRoute(conn, command.query, false, null); if (pools == null) { conn.postMessage(STATIC_OK_BUFFER); return; } MessageHandler handler = new QueryCommandMessageHandler(conn, message, pools, timeout); if (handler instanceof Sessionable) { Sessionable session = (Sessionable) handler; try { session.startSession(); } catch (Exception e) { logger.error("start Session error:", e); session.endSession(); throw e; } } } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_STMT_PREPARE)) { PreparedStatmentInfo preparedInf = conn.getPreparedStatmentInfo(command.query); byte[] buffer = preparedInf.getByteBuffer(); conn.postMessage(buffer); return; } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_STMT_SEND_LONG_DATA)) { conn.addLongData(message); } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_STMT_EXECUTE)) { long statmentId = ExecutePacket.readStatmentID(message); PreparedStatmentInfo preparedInf = conn.getPreparedStatmentInfo(statmentId); if (preparedInf == null) { ErrorPacket error = new ErrorPacket(); error.errno = 1044; error.packetId = 1; error.sqlstate = "42000"; error.serverErrorMessage = "Unknown prepared statment id=" + statmentId; conn.postMessage(error.toByteBuffer(connection).array()); logger.warn("Unknown prepared statment id:" + statmentId); } else { Map<Integer, Object> longMap = new HashMap<Integer, Object>(); for (byte[] longdate : conn.getLongDataList()) { LongDataPacket packet = new LongDataPacket(); packet.init(longdate, connection); longMap.put(packet.parameterIndex, packet.data); } ExecutePacket executePacket = new ExecutePacket(preparedInf, longMap); executePacket.init(message, connection); QueryRouter router = ProxyRuntimeContext.getInstance().getQueryRouter(); ObjectPool[] pools = router.doRoute(conn, preparedInf.getPreparedStatment(), false, executePacket.getParameters()); PreparedStatmentExecuteMessageHandler handler = new PreparedStatmentExecuteMessageHandler( conn, preparedInf, message, pools, timeout); if (handler instanceof Sessionable) { Sessionable session = (Sessionable) handler; try { session.startSession(); } catch (Exception e) { logger.error("start Session error:", e); session.endSession(); throw e; } } } } else if (MysqlPacketBuffer.isPacketType(message, QueryCommandPacket.COM_INIT_DB)) { conn.setSchema(command.query); conn.postMessage(STATIC_OK_BUFFER); } else { ErrorPacket error = new ErrorPacket(); error.errno = 1044; error.packetId = 1; error.sqlstate = "42000"; error.serverErrorMessage = "can not use this command here!!"; conn.postMessage(error.toByteBuffer(connection).array()); logger.warn("unsupport packet:" + command); } } catch (Exception e) { ErrorPacket error = new ErrorPacket(); error.errno = 1044; error.packetId = 1; error.sqlstate = "42000"; error.serverErrorMessage = e.getMessage(); conn.postMessage(error.toByteBuffer(connection).array()); logger.error("messageDispate error", e); } } }