一个连接池的例子(来自JIVE)(2)

发表于:2007-07-01来源:作者:点击数: 标签:
//文件:DbConnectionDefaultPool. java 的第二部分 /** * Housekeeping thread.Runs in the background with low CPU overhead. * Connections are checked for warnings and closure and are periodically * restarted. * This thread is a catchall for co
//文件:DbConnectionDefaultPool.java的第二部分


        /**
         * Housekeeping thread.  Runs in the background with low CPU overhead.
         * Connections are checked for warnings and closure and are periodically
         * restarted.
         * This thread is a catchall for corrupted
         * connections and prevents the buildup of open cursors. (Open cursors
         * result when the application fails to close a Statement).
         * This method acts as fault tolerance for bad connection/statement programming.
         */
        public void run() {
            boolean forever = true;
            Statement stmt=null;
            String currCatalog=null;

            while(forever) {

                // Make sure the log file is the one this instance opened
                // If not, clean it up!
                try {
                    BufferedReader in = new BufferedReader(new
                        FileReader(logFileString + "pid"));
                    String curr_pid = in.readLine();
                    if(curr_pid.equals(pid)) {
                        //log.println("They match = " + curr_pid);
                    }
                    else {
                        //log.println("No match = " + curr_pid);
                        log.close();

                        // Close all connections silently - they are definitely dead.
                        for(int i=0; i < currConnections; i++) {
                            try {
                                connPool[i].close();
                            }
                            catch (SQLException e1) {} // ignore
                        }
                        // Returning from the run() method kills the thread
                        return;
                    }
                    in.close();
                }
                catch (IOException e1) {
                    log.println("Can@#t read the file for pid info: " +
                        logFileString + "pid");
                }

                // Get any Warnings on connections and print to event file
                for(int i=0; i < currConnections; i++) {
                    try {
                        currSQLWarning = connPool[i].getWarnings();
                        if(currSQLWarning != null) {
                            log.println("Warnings on connection " +
                                String.valueOf(i) + " " + currSQLWarning);
                            connPool[i].clearWarnings();
                        }
                    }
                    catch(SQLException e) {
                        log.println("Cannot aclearcase/" target="_blank" >ccess Warnings: " + e);
                    }
                }

                for(int i=0; i < currConnections; i++) { // Do for each connection
                    long age = System.currentTimeMillis() - connCreateDate[i];

                    synchronized(connStatus) {
                        if(connStatus[i] > 0) { // In use, catch it next time!
                            continue;
                        }
                        connStatus[i] = 2; // Take offline (2 indicates housekeeping lock)
                    }
        
                    try {  // Test the connection with createStatement call
                        if(age > maxConnMSec) {  // Force a reset at the max conn time
                            throw new SQLException();
                        }

                        stmt = connPool[i].createStatement();
                        connStatus[i] = 0;  // Connection is O.K.
                        //log.println("Connection confirmed for conn = " +
                        //             String.valueOf(i));

                        // Some DBs return an object even if DB is shut down
                        if(connPool[i].isClosed()) {
                            throw new SQLException();
                        }
                        // Connection has a problem, restart it
                    }
                    catch(SQLException e) {
                        try {
                            log.println(new Date().toString() +
                            " ***** Recycling connection " +
                            String.valueOf(i) + ":");

                            connPool[i].close();
                            createConn(i);
                        }
                        catch(SQLException e1) {
                            log.println("Failed: " + e1);
                            connStatus[i] = 0;  // Can@#t open, try again next time
                        }
                    }
                    finally {
                        try {
                            if(stmt != null) {
                                stmt.close();
                            }
                        }
                        catch(SQLException e1){};
                    }
                }

                try {
                    Thread.sleep(20000);
                }  // Wait 20 seconds for next cycle
                catch(InterruptedException e) {
                    // Returning from the run method sets the internal
                    // flag referenced by Thread.isAlive() to false.
                    // This is required because we don@#t use stop() to
                    // shutdown this thread.
                    return;
                }
            }
        } // End run

        /**
         * This method hands out the connections in round-robin order.
         * This prevents a faulty connection from locking
         * up an application entirely.  A browser @#refresh@# will
         * get the next connection while the faulty
         * connection is cleaned up by the housekeeping thread.
         *
         * If the min number of threads are ever exhausted, new
         * threads are added up the the max thread count.
         * Finally, if all threads are in use, this method waits
         * 2 seconds and tries again, up to ten times.  After that, it
         * returns a null.
         */
        public Connection getConnection() {

            Connection conn=null;

            if(available){
                boolean gotOne = false;

                for(int outerloop=1; outerloop<=10; outerloop++) {

                    try  {
                        int loop=0;
                        int roundRobin = connLast + 1;
                        if(roundRobin >= currConnections) roundRobin=0;

                        do {
                            synchronized(connStatus) {
                                if((connStatus[roundRobin] < 1) &&
                                        (! connPool[roundRobin].isClosed()))
                                {
                                    conn = connPool[roundRobin];
                                    connStatus[roundRobin]=1;
                                    connLockTime[roundRobin] =
                                        System.currentTimeMillis();
                                    connLast = roundRobin;
                                    gotOne = true;
                                    break;
                                }
                                else {
                                    loop++;
                                    roundRobin++;
                                    if(roundRobin >= currConnections) roundRobin=0;
                                }
                            }
                        }
                        while((gotOne==false)&&(loop < currConnections));
                    }
                    catch (SQLException e1) {}

                    if(gotOne) {
                        break;
                    }
                    else {
                        synchronized(this) {  // Add new connections to the pool
                            if(currConnections < maxConns) {
                                try {
                                    createConn(currConnections);
                                    currConnections++;
                                }
                                catch(SQLException e) {
                                    log.println("Unable to create new connection: " + e);
                                }
                            }
                        }

                        try { Thread.sleep(2000); }
                        catch(InterruptedException e) {}
                        log.println("-----> Connections Exhausted!  Will wait and try " +
                            "again in loop " +
                            String.valueOf(outerloop));
                    }
                } // End of try 10 times loop

            }
            else {
                log.println("Unsuccessful getConnection() request during destroy()");
            } // End if(available)

            return conn;
        }

        /**
         * Returns the local JDBC ID for a connection.
         */
        public int idOfConnection(Connection conn) {
            int match;
            String tag;

            try {
                tag = conn.toString();
            }
            catch (NullPointerException e1) {
                tag = "none";
            }

            match=-1;

            for(int i=0; i< currConnections; i++) {
                if(connID[i].equals(tag)) {
                    match = i;
                    break;
                }
            }
            return match;
        }

        /**
         * Frees a connection.  Replaces connection back into the main pool for
         * reuse.
         */
        public String freeConnection(Connection conn) {
            String res="";

            int thisconn = idOfConnection(conn);
            if(thisconn >= 0) {
                connStatus[thisconn]=0;
                res = "freed " + conn.toString();
                //log.println("Freed connection " + String.valueOf(thisconn) +
                //            " normal exit: ");
            }
            else {
                log.println("----> Could not free connection!!!");
            }

            return res;
        }

原文转自:http://www.ltesting.net