⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namedconnectionpool.java

📁 java开源的企业总线.xmlBlaster
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------------Name:      NamedConnectionPool.javaProject:   xmlBlaster.orgCopyright: jutils.org, see jutils-LICENSE fileComment:   Basic handling of a pool of limited resourcesAuthor:    xmlBlaster@marcelruff.info------------------------------------------------------------------------------*/package org.xmlBlaster.protocol.jdbc;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.def.ErrorCode;import java.util.logging.Logger;import java.util.logging.Level;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.I_Timeout;import org.xmlBlaster.util.Timestamp;import org.xmlBlaster.util.pool.PoolManager;import org.xmlBlaster.util.pool.I_PoolManager;import org.xmlBlaster.util.pool.ResourceWrapper;import java.util.Hashtable;import java.util.Enumeration;import java.sql.Connection;import java.sql.DriverManager;/** * This is a specialized JDBC connection pool for xmlBlaster. * <p /> * It allows accessing any number of different databases with * arbitrary login users.<br /> * Every database user is separately pooled for maximum performance.<br /> * Every DB request needs to pass the DB-url, login name and password, * since the clients are not permanently connected.<br /> * Unused connection pools are freed after some time. * <p /> * The timeout parameters and pool size is adjustable. * <p /> * The connections are established on demand (lazy allocation). * Pre-allocation is currently not implemented. * The first SQL request (for example with Oracle) consumes about * 1 second to establish the connection, the following requests * get this connection from the pool, which is below 1 millisecond. * If more than one SQL requests are done simultaneously, the pool * increases the number of parallel connections. * <p /> * Load the drivers before using this pool, e.g.<br /> * <pre> *    java -Djdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver ... * </pre> * or in xmlBlaster.properties, e.g.<br /> * <pre> *    JdbcDriver.drivers=oracle.jdbc.driver.OracleDriver,org.gjt.mm.mysql.Driver:postgresql.Driver,de.sag.jdbc.adabasd.ADriver:sun.jdbc.odbc.JdbcOdbcDriver:com.sybase.jdbc2.jdbc.SybDriver * </pre> * You use reserve() to get a connection and need to call release() after using it, * note that the connection parameters are optional: * <pre> *    String dbStmt = "select * from user_table"; *    java.sql.Connection con = namedPool.reserve(dbUrl, dbUser, dbPasswd, 60*60*1000L, 100, 10*60*1000L); *    java.sql.Statement stmt = null; *    java.sql.ResultSet rs = null; *    try { *       stmt = con.createStatement(); *       rs = stmt.executeQuery(dbStmt); *    } finally { *       if (rs!=null) rs.close(); *       if (stmt!=null) stmt.close(); *       if (con!=null) namedPool.release(dbUrl, user, pw, con); *    } * </pre> * @see         org.xmlBlaster.util.pool.PoolManager * @see         org.xmlBlaster.util.pool.ResourceWrapper * @since       xmlBlaster 0.78 */public class NamedConnectionPool {   private static final String ME = "NamedConnectionPool";   private Global glob;   private static Logger log = Logger.getLogger(NamedConnectionPool.class.getName());   private Hashtable namedPools = new Hashtable();   private final Object meetingPoint = new Object();   NamedConnectionPool(Global glob)   {      this.glob = glob;   }   /**    * Use this method to get a JDBC connection.    * <br />    * The pooling properties are set to default values.    * @param dbUrl    For example "jdbc:oracle:thin:@localhost:1521:mydb    * @param dbUser   The database user    * @param dbPasswd The database password    */   Connection reserve(String dbUrl, String dbUser, String dbPasswd) throws XmlBlasterException   {      return reserve(dbUrl, dbUser, dbPasswd, -1, -1, -1);   }   /**    * Use this method to get a JDBC connection.    * <br />    * Usually only the first time for a user, to specify all parameters.    * @param dbUrl For example "jdbc:oracle:thin:@localhost:1521:mydb    * @param eraseUnusedPoolTimeout Remove pool of a user if not in use, in ms    *          0 switches it off, -1 uses default setting 1 hour (from xmlBlaster.properties)    * @param maxInstances Default is max. 20 connections (from xmlBlaster.properties)    * @param idleToErase  in msec    *          0 switches it off, -1 uses default setting 10 min. (from xmlBlaster.properties)    */   Connection reserve(String dbUrl, String dbUser, String dbPasswd, long eraseUnusedPoolTimeout,                      int maxInstances, long idleToErase) throws XmlBlasterException   {      long busyToIdle = 0L; // On timeout it changes state from 'busy' to 'idle': switched off!      UnnamedConnectionPool pool = getPool(dbUrl, dbUser, dbPasswd);      if (pool == null) { // check before as well to increase performance         synchronized(meetingPoint) {            pool = getPool(dbUrl, dbUser, dbPasswd);            if (pool == null) {               if (dbPasswd == null) throw new XmlBlasterException(glob, ErrorCode.RESOURCE_CONFIGURATION, ME+".MissingPasswd", "Please give a password for '" + dbUser + "' when creating a JDBC pool");               pool = new UnnamedConnectionPool(this, dbUrl, dbUser, dbPasswd, eraseUnusedPoolTimeout, maxInstances, busyToIdle, idleToErase);               namedPools.put(getKey(dbUrl, dbUser, dbPasswd), pool);            }         }      }      try {         Connection con = pool.reserve();         if (log.isLoggable(Level.FINE)) log.fine("reserve(" + dbUrl + ", " + dbUser + ") con=" + con);         return con;      }      catch(XmlBlasterException e) {         throw e;      }      catch(Throwable e) {         log.severe("Unexpected exception in connect(" + dbUrl + ", " + dbUser + "): " + e.toString());         throw new XmlBlasterException(glob, ErrorCode.RESOURCE_CONFIGURATION, ME+".NoOpen", "Couldn't open database connection: " + e.toString());      }   }   /**    * Use this method to release a JDBC connection.    */   void release(String dbUrl, String dbUser, String dbPasswd, Connection con) throws XmlBlasterException   {      UnnamedConnectionPool pool = getPool(dbUrl, dbUser, dbPasswd);      if (pool != null) {         pool.release(con);         if (log.isLoggable(Level.FINE)) log.fine("release(" + dbUrl + ", " + dbUser + ") con=" + con);      }   }   /**    * Use this method to destroy the given JDBC connection.    */   void eraseConnection(String dbUrl, String dbUser, String dbPasswd, Connection con) throws XmlBlasterException {      UnnamedConnectionPool pool = getPool(dbUrl, dbUser, dbPasswd);      if (pool != null) {         if (log.isLoggable(Level.FINE)) log.fine("erase(" + dbUrl + ", " + dbUser + ") con=" + con);         pool.erase(con);      }   }   /**    * Destroy the JDBC connection pool from a specific user.    * The driver remains.    * @param The UnnamedConnectionPool object    */   void destroy(String dbUrl, String dbUser, String dbPasswd) throws XmlBlasterException   {      if (log.isLoggable(Level.FINE)) log.fine("Entering destroy() ...");      try {         String key = getKey(dbUrl, dbUser, dbPasswd);         UnnamedConnectionPool pool = (UnnamedConnectionPool)namedPools.remove(key);         if (pool != null)            pool.destroy();         if (log.isLoggable(Level.FINE)) log.fine("All JDBC connections for '" + dbUrl + "' destroyed");      }      catch (Exception e) {         log.severe("System Exception in destroy JDBC connection for '" + dbUrl + "': " + e.toString());         throw new XmlBlasterException(glob, ErrorCode.RESOURCE_DB_UNKNOWN, ME+".DestroyError", "System Exception in destroy JDBC connection for '" + dbUrl + "': " + e.toString());      }   }   /**    * Destroy the complete named pool of all users.    * This object is still valid for further use.    */   void destroy()   {      for (Enumeration e = namedPools.elements() ; e.hasMoreElements() ;) {         UnnamedConnectionPool pool = (UnnamedConnectionPool)e.nextElement();         pool.destroy();      }      namedPools.clear();   }   /**    * @return instanceId <db_url>^<username>/<passwd>, e.g.  "jdbc:oracle:thin:@localhost:1521:mydb^jack/secret"    */   private String getKey(String dbUrl, String dbUser, String dbPasswd)   {      StringBuffer buf = new StringBuffer(80);      return buf.append(dbUrl).append("^").append(dbUser).append("/").append(dbPasswd).toString();   }   private UnnamedConnectionPool getPool(String dbUrl, String dbUser, String dbPasswd)   {      String key = getKey(dbUrl, dbUser, dbPasswd);      return (UnnamedConnectionPool)namedPools.get(key);   }   /**    * Dump state of this object into a XML ASCII string.    */   public final String toXml()   {      StringBuffer buf = new StringBuffer(256);      String offset = "\n";      buf.append(offset).append("<").append(ME).append(">");      buf.append(offset).append("   <namedPools num='").append(namedPools.size()).append("'>");      for (Enumeration e = namedPools.elements() ; e.hasMoreElements() ;) {         UnnamedConnectionPool pool = (UnnamedConnectionPool)e.nextElement();         buf.append(pool.toXml());      }      buf.append(offset).append("   </namedPools>");      buf.append(offset).append("</" + ME + ">");      return buf.toString();   }   /**    * Inner class, every user of the Named pool has its own connection pool.    * <p />    * If the resource pool is exhausted, the request will poll for a connection    * 5 times, with 1 sec sleeping in between.<br />    * This feature is adjustable in xmlBlaster.properties with:<br />    * <pre>    *   JdbcPool.maxResourceExhaustRetries=5    *   JdbcPool.resourceExhaustSleepGap=1000    * </pre>    */   private class UnnamedConnectionPool implements I_PoolManager, I_Timeout   {      private static final String ME = "UnnamedConnectionPool";      private NamedConnectionPool boss = null;      PoolManager poolManager = null;      private String dbUrl;      private String dbUser;      private String dbPasswd;      private long eraseUnusedPoolTimeout;      /** If the pool is exhausted, we poll the given times */      private int maxResourceExhaustRetries;      /** If the pool is exhausted, we poll every given millis<br />          Please note that the current request thread will block for maxResourceExhaustRetries*resourceExhaustSleepGap millis. */      private long resourceExhaustSleepGap;      private Timestamp timeoutHandle;      private final Object timeoutMonitor = new Object();      private final Object meetingPoint = new Object();      /**       * @param boss           My manager       * @param eraseUnusedPoolTimeout This pool is erased after given millis without activity of the owning user<br />       *                       0 switches it off, -1 looks into env JdbcPool.eraseUnusedPoolTimeout setting (and defaults to one hour)       * @param maxInstances   Max. number of resources in this pool.       *                       -1 uses default of 20 (xmlBlaster.properties)<br />       * @param busyToIdleTimeout Max. busy time of this resource in milli seconds<br />       *                       On timeout it changes state from 'busy' to 'idle'.<br />       *                       You can overwrite this value for each resource instance<br />       *                       0 switches it off<br />       *                       -1 uses default (switched off)<br />       *                       You get called back through I_PoolManager.busyToIdle() on timeout       *                       allowing you to code some specific handling.       * @param idleToEraseTimeout Max. idle time span of this resource in milli seconds<br />       *                     On timeout it changes state from 'idle' to 'undef' (it is deleted).<br />       *                     You can overwrite this value for each resource instance<br />       *                     0 switches it off<br />       *                     -1 uses default (10 min) (xmlBlaster.properties)<br />       *                     You get called back through I_PoolManager.toErased() on timeout       *                     allowing you to code some specific handling.       */      public UnnamedConnectionPool(NamedConnectionPool boss, String dbUrl, String dbUser, String dbPasswd,                                   long eraseUnusedPoolTimeout, int maxInstances, long busyToIdle, long idleToErase)      {         this.boss = boss;         this.dbUrl = dbUrl;         this.dbUser = dbUser;         this.dbPasswd = dbPasswd;         this.eraseUnusedPoolTimeout = eraseUnusedPoolTimeout;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -