package com.meidusa.amoeba.aladdin.handler; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; 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.result.ResultPacket; 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.net.poolable.PoolableObject; /** * @author struct * @author hexianmao */ public abstract class CommandMessageHandler implements MessageHandler, Sessionable { private static Logger logger = Logger.getLogger(CommandMessageHandler.class); protected MysqlClientConnection source; protected String query; protected ResultPacket packet = null; private Object parameter; private ObjectPool[] pools; private long timeout; private long createTime; private long endTime; private boolean ended = false; private final Lock lock = new ReentrantLock(false); private Map<Object, ObjectPool> connPoolMap = new HashMap<Object, ObjectPool>(); private boolean started; public CommandMessageHandler(MysqlClientConnection source, String query, Object parameter, ObjectPool[] pools, long timeout){ this.source = source; this.query = query; this.pools = pools; this.timeout = timeout; this.parameter = parameter; this.packet = newResultPacket(query); } public boolean isMultiplayer(){ return pools.length>1; } public void handleMessage(Connection conn) { return; } 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 boolean isStarted(){ return this.started; } public void startSession() throws Exception { if (pools.length == 1) { final PoolableObject conn = (PoolableObject) pools[0].borrowObject(); connPoolMap.put(conn, pools[0]); MessageHandlerRunner runnable = null; if (conn instanceof MessageHandlerRunnerProvider) { MessageHandlerRunnerProvider provider = (MessageHandlerRunnerProvider) conn; runnable = provider.getRunner(); } else { runnable = newQueryRunnable(null, conn, query, parameter, packet); } started = true; runnable.init(this); runnable.run(); } else { final CountDownLatch latch = new CountDownLatch(pools.length); for (ObjectPool pool : pools) { final PoolableObject conn = (PoolableObject) pool.borrowObject(); connPoolMap.put(conn, pool); QueryRunnable runnable = newQueryRunnable(latch, conn, query, parameter, packet); runnable.init(this); ProxyRuntimeContext.getInstance().getRuntimeContext().getClientSideExecutor().execute(runnable); } started = true; if (timeout > 0) { latch.await(timeout, TimeUnit.MILLISECONDS); } else { latch.await(); } } endSession(false); packet.wirteToConnection(source); } protected abstract ResultPacket newResultPacket(String query); protected abstract QueryRunnable newQueryRunnable(CountDownLatch latch, PoolableObject conn, String query2, Object parameter, ResultPacket packet); public void endSession(boolean force) { if (isEnded()) { return; } lock.lock(); try { if (!ended) { endTime = System.currentTimeMillis(); ended = true; for (Map.Entry<Object, ObjectPool> entry : connPoolMap.entrySet()) { try { entry.getValue().returnObject(entry.getKey()); } catch (Exception e) { logger.error("return connection to pool error", e); } } } } finally { lock.unlock(); } } public boolean isEnded() { lock.lock(); try { return this.ended; } finally { lock.unlock(); } } }