Key Mapped DBCP







 해쉬코드를 키값으로 하는 DBConnection Pool을 한번 만들어 보았다..



/**
 * <p>Title: ConnectionPool</p>
 * <p>Description: ConnectionPool</p>
 * <p>Copyright: Copyright (c) 2005 Maxoft.Inc</p>
 * <p>Company: Maxoft.Inc </p>
 * @author Kim sooki
 * @version 1.0
 */
package net.maxoft.center.controller;



import com.mysql.jdbc.Statement;
import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import net.maxoft.model.GlobalsFactory;
import org.apache.log4j.Logger;

public class ConnectionPool extends Thread {
 


  public static synchronized ConnectionPool getInstance(){
    if(instance == null){
      instance = new ConnectionPool();
    }
    return instance;
  }

 private ConnectionPool() {
    use = 0;
    close = false;
    available = 0;
   
    pool = new HashMap();
    keyMap = new HashMap();
   
    try{
      makeConnections();
    }catch(Exception e){
      e.printStackTrace();
      running = false;
      logger.debug(“Connection pool create fail!!”);
    }
    logger.info(“Connection Pool created!!”);  
 } 

 private void makeConnections() throws SQLException{
   
    for(int i = 0 ; i < ConnectionPool.MAX_ALIVE; i++){       
      try{
        Class.forName(GlobalsFactory.getGlobals().getProperty(“jdbcDriverClass”)).newInstance();
        String URL = GlobalsFactory.getGlobals().getProperty(“jdbcConnectionUrl”);
        Connection connection = DriverManager.getConnection(URL,”root”,”****”);
        int hash = connection.hashCode();
        pool.put(new Integer(hash), connection);
        keyMap.put(new Integer(hash), new Integer(hash));
        logger.debug(“Make connection  : “+ connection + ” / ” + hash + ”  / ” + available);
        available++;
       
      }catch(Exception e){
        e.printStackTrace();       
      }    
    }
   
    if( pool.size() == 0){
      throw new SQLException(“Create fail Connection!!!”);
    }
    logger.debug(“Connection : ” + available + ” created!”);
 }
 
  private Connection addConnection() throws SQLException {
    try{
      Class.forName(GlobalsFactory.getGlobals().getProperty(“jdbcDriverClass”)).newInstance();
      String URL = GlobalsFactory.getGlobals().getProperty(“jdbcConnectionUrl”);
      Connection connection = DriverManager.getConnection(URL,”root”,”****”);  
      logger.debug(connection);
      return connection;
     
    }catch(Exception e){
      e.printStackTrace();    
      throw new SQLException(“Connection create fail!”);
    }      
  }
 
  private void closeAllConnection(){
   
    Iterator iter = pool.keySet().iterator();
    while(iter.hasNext()){
      Integer hash = (Integer)iter.next();
      Connection con = null;
      try{
        con = (Connection)pool.remove(hash);
        con.close();
        available–;
       
      }catch(Exception e){
        e.printStackTrace();       
      }finally {
        if(con != null){
          try{
            con.close();
          }catch(Exception e){
          } // inner try – catch;
        }  // if(con != null)    
      } // outter try – catch;     
    } // while – iterator
    logger.debug(“Connection all closed!!”); 
  }
 
  protected void finalize() throws Throwable {
    if(close != false){
      close();     
    }
    super.finalize();
  } 



  public synchronized void close(){
    if(close == true)
      return;
    close = true;
    closeAllConnection();
    pool = null;
  }
 
  public synchronized void releaseConnection(Connection con) throws SQLException { 
    if(con == null){
      throw new SQLException(“Connection is null!!”);
    }
     
    synchronized(pool){
      int hash = con.hashCode();
      if(keyMap.containsKey(new Integer(hash))){
        pool.put(new Integer(hash), con);
        available++;
        use–;
      } else {
        try{
          con.close();
        }catch(Exception e){
          logger.debug(“Close connection error!”);
          e.printStackTrace();
          throw new SQLException(“Close connection error!”);
        }
      }
    }
  }
 
  public synchronized Connection getConnection() throws SQLException {       
     
    if(use > 50){
      throw new SQLException(“MAX Connection Alive!!”);
    }       
    synchronized(pool){
      if(pool.size() > 0){
        Iterator iter = pool.keySet().iterator();
        if(!iter.hasNext())
          logger.debug(“key not exist!!”);
         
        Integer hash = (Integer)iter.next();
        Connection con = (Connection)pool.remove(hash);
        available–;
        use++;       
        return con;
      }      
    }  
    return addConnection();   
  } 
 
 
  public void run(){
    // 시간마다 avaliable connection의 상태를 점검
    // 연결이 닫혔으면 map에서 삭제하고 다시 연결한뒤 저장
    // Connection에러가 발생하여 0개의 conn이 유효한경우 종료
    // running = false 인경우 종료
  }
 
 
  private Connection con; 
  private boolean running = true;
  private static final int MAX_ALIVE = 10;
  private int available;
  private int use;
  private HashMap pool;
  private HashMap keyMap; 
  private static ConnectionPool instance;
  private boolean close;
  private static final Logger logger;
   
  static
  {
      logger = Logger.getLogger(net.maxoft.center.controller.ConnectionPool.class);
  }
 


}

Connection Pool 자체를 Thread로 설정하여 일정주기동안 Managed connection의 validate를 check 하도록 추가해 주어야 한다.



MAX_ALIVE의 갯수를 넘어서는 Connection요청은 Connection을 생성후 반납시 close()하도록 되어 있다.



드라이버이름과 URL은 Pref를 구현한 클래스로부터 얻어오도록 되어 있으므로 Prefs를 직접구현하도록 한다.

답글 남기기

이메일 주소는 공개되지 않습니다.