package jef.database.innerpool; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import javax.sql.DataSource; import jef.database.datasource.DataSources; import jef.database.datasource.IRoutingDataSource; import jef.tools.Assert; /** * 路由数据源连接池,其中每个数据源都被装在一个小池(SimplePool,DummyPool)里。 * 每个小池按照预先的配置来管理大小。 * 从这个连接池中获得的IConnection对象都是支持路由的。 * 选择合适的连接进行路由等操作,都封装在IConnection内部实现了。因此对于外部使用者来说,不需要关心IConnection是指向那个真正的数据源的 * * * @author jiyi * */ public final class RoutingManagedConnectionPool extends RoutingDummyConnectionPool { private int min; private int max; private boolean autoPool; //所有已知数据源的缓存连接,按数据源的key分别存放 //特点,元素数量不多,用较大的空间避免元素冲突 private final HashMap<String, IPool<Connection>> cache=new HashMap<String, IPool<Connection>>(8,0.5f); /** * 构造 * @param ds 路由数据源 * @param max 连接池最大 * @param min 连接池最小 * @param autoPool */ RoutingManagedConnectionPool(IRoutingDataSource ds,int max,int min,boolean autoPool) { super(ds); this.min=min; this.max=max; this.autoPool=autoPool; } /** * 从缓存中获取连接 */ @Override public Connection getCachedConnection(String ds) throws SQLException { IPool<Connection> queue=cache.get(ds); if(queue==null){ queue=putDsItem(ds); } return queue.poll(); } /** * 将连接放回缓存 */ @Override public void putback(String ds, Connection conn){ IPool<Connection> queue=cache.get(ds); if(queue==null){ queue=putDsItem(ds); } queue.offer(conn); } private synchronized IPool<Connection> putDsItem(String ds) { IPool<Connection> queue=cache.get(ds); if(queue!=null)return queue; DataSource realds=datasource.getDataSource(ds); if(autoPool && !DataSources.isPool(realds)){ queue=new SimplePooledDatasource(min,max,realds); }else{ queue=new DummyPool(realds); } IPool<Connection> old=cache.put(ds, queue); Assert.isNull(old);//高并发下是否可能出现其他问题,对此进行检查 return queue; } public PrintWriter getLogWriter() throws SQLException { throw new UnsupportedOperationException("getLogWriter"); } public void setLogWriter(PrintWriter out) throws SQLException { throw new UnsupportedOperationException("setLogWriter"); } public void setLoginTimeout(int seconds) throws SQLException { throw new UnsupportedOperationException("setLoginTimeout"); } public int getLoginTimeout() throws SQLException { return 0; } @SuppressWarnings("unchecked") public <T> T unwrap(Class<T> iface) throws SQLException { Assert.notNull(iface, "Interface argument must not be null"); if (!DataSource.class.equals(iface)) { throw new SQLException( "DataSource of type [" + getClass().getName() + "] can only be unwrapped as [javax.sql.DataSource], not as [" + iface.getName()); } return (T) this; } public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; } public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } @Override public boolean isDummy() { return false; } public Map<String, IPool<Connection>> getCachedPools(){ return cache; } }