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

📄 dbconnectionmanager.java

📁 一个用jsp技术实现的新闻发布系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package net.ijsp.download.database;

/** 
 * DbConnectionBroker.  
 * @version 1.0.13 3/12/02
 * @author Marc A. Mnich
 */
import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.Date;


/**
 * DbConnectionBroker
 * A servlet-based broker for database connections.
 * Creates and manages a pool of database connections.
 * @version 1.0.13 3/12/02
 * @author Marc A. Mnich
 */
public class DBConnectionManager implements Runnable {
    private Thread runner;
    
    private Connection[] connPool;
    private int[] connStatus;

    private long[] connLockTime, connCreateDate;
    private String[] connID;
    private String dbDriver, dbServer, dbLogin, dbPassword, logFileString;
    private int currConnections, connLast, minConns, maxConns, maxConnMSec,
	maxCheckoutSeconds, debugLevel;

    //available: set to false on destroy, checked by getConnection()
    private boolean available=true;

    private PrintWriter log;
    private SQLWarning currSQLWarning;
    private String pid;

    private final int DEFAULTMAXCHECKOUTSECONDS=60;
    private final int DEFAULTDEBUGLEVEL=2;
    
    /**
     * Creates a new Connection Broker<br>
     * dbDriver:        JDBC driver. e.g. 'oracle.jdbc.driver.OracleDriver'<br>
     * dbServer:        JDBC connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'<br>
     * dbLogin:         Database login name.  e.g. 'Scott'<br>
     * dbPassword:      Database password.    e.g. 'Tiger'<br>
     * minConns:        Minimum number of connections to start with.<br>
     * maxConns:        Maximum number of connections in dynamic pool.<br>
     * logFileString:   Absolute path name for log file. e.g. 'c:/temp/mylog.log' <br>
     * maxConnTime:     Time in days between connection resets. (Reset does a basic cleanup)<br>
     * logAppend:       Append to logfile (optional)<br>
     * maxCheckoutSeconds:       Max time a connection can be checked out before being recycled. Zero value turns option off, default is 60 seconds.
     * debugLevel:      Level of debug messages output to the log file.  0 -> no messages, 1 -> Errors, 2 -> Warnings, 3 -> Information
     */
    public DBConnectionManager(String dbDriver, String dbServer, String dbLogin,
        String dbPassword, int minConns, int maxConns,
            String logFileString, double maxConnTime) throws IOException {
	
	setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns, 
		    maxConns, logFileString, maxConnTime, false, 
		    DEFAULTMAXCHECKOUTSECONDS, DEFAULTDEBUGLEVEL);
    }

    /*
     * Special constructor to handle logfile append
     */
    public DBConnectionManager(String dbDriver, String dbServer, String dbLogin,
        String dbPassword, int minConns, int maxConns,
            String logFileString, double maxConnTime, boolean logAppend) 
	throws IOException {
	
	setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns, 
		    maxConns, logFileString, maxConnTime, logAppend,
		    DEFAULTMAXCHECKOUTSECONDS, DEFAULTDEBUGLEVEL);
    }

    /*
     * Special constructor to handle connection checkout expiration
     */
    public DBConnectionManager(String dbDriver, String dbServer, String dbLogin,
        String dbPassword, int minConns, int maxConns,
            String logFileString, double maxConnTime, boolean logAppend,
			      int maxCheckoutSeconds, int debugLevel) 
	throws IOException {
	
	setupBroker(dbDriver, dbServer, dbLogin, dbPassword, minConns, 
		    maxConns, logFileString, maxConnTime, logAppend, 
		    maxCheckoutSeconds, debugLevel);
    }



    private void setupBroker(String dbDriver, String dbServer, String dbLogin,
        String dbPassword, int minConns, int maxConns,
            String logFileString, double maxConnTime, boolean logAppend,
			     int maxCheckoutSeconds, int debugLevel) 
	throws IOException {
            
        connPool = new Connection[maxConns];
        connStatus = new int[maxConns];
        connLockTime = new long[maxConns];
        connCreateDate = new long[maxConns];
        connID = new String[maxConns];
        currConnections = minConns;
        this.maxConns = maxConns;
        this.dbDriver = dbDriver;
        this.dbServer = dbServer;
        this.dbLogin = dbLogin;
        this.dbPassword = dbPassword;
        this.logFileString = logFileString;
	this.maxCheckoutSeconds = maxCheckoutSeconds;
	this.debugLevel = debugLevel;
        maxConnMSec = (int)(maxConnTime * 86400000.0);  //86400 sec/day
        if(maxConnMSec < 30000) {  // Recycle no less than 30 seconds.
            maxConnMSec = 30000;
        }
        

        try {
	    log = new PrintWriter(new FileOutputStream(logFileString,
						       logAppend),true);
	    
	    // Can't open the requested file. Open the default file.
        } catch (IOException e1) {  
	    try {
		log = new PrintWriter(new FileOutputStream("DCB_" +
					   System.currentTimeMillis() + ".log",
					   logAppend),true);
		
	    } catch (IOException e2) {
		throw new IOException("Can't open any log file");
	    }
        }
	

	
	// Write the pid file (used to clean up dead/broken connection)
	SimpleDateFormat formatter
	    = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz");
	Date nowc = new Date();
	pid = formatter.format(nowc);
	
	BufferedWriter pidout = new BufferedWriter(new 
	    FileWriter(logFileString + "pid"));
	pidout.write(pid);
	pidout.close();
	
        log.println("-----------------------------------------");
        log.println("-----------------------------------------");
        log.println("Starting DbConnectionBroker Version 1.0.13:");
        log.println("dbDriver = " + dbDriver);
        log.println("dbServer = " + dbServer);
        log.println("dbLogin = " + dbLogin);
        log.println("log file = " + logFileString);
        log.println("minconnections = " + minConns);
        log.println("maxconnections = " + maxConns);
        log.println("Total refresh interval = " + maxConnTime + " days");
        log.println("logAppend = " + logAppend);
        log.println("maxCheckoutSeconds = " + maxCheckoutSeconds);
	log.println("debugLevel = " + debugLevel);
        log.println("-----------------------------------------");
        
        
        // Initialize the pool of connections with the mininum connections:
        // Problems creating connections may be caused during reboot when the
        //    servlet is started before the database is ready.  Handle this
        //    by waiting and trying again.  The loop allows 5 minutes for 
        //    db reboot.
        boolean connectionsSucceeded=false;
        int dbLoop=20;
        
        try {
            for(int i=1; i < dbLoop; i++) {
                try {
                    for(int j=0; j < currConnections; j++) { 
                        createConn(j);
                    }
                    connectionsSucceeded=true;
                    break;
                } catch (SQLException e){
		    if(debugLevel > 0) {
			log.println("--->Attempt (" + String.valueOf(i) +
				    " of " + String.valueOf(dbLoop) + 
				    ") failed to create new connections set at startup: ");
			log.println("    " + e);
			log.println("    Will try again in 15 seconds...");
		    }
		    try { Thread.sleep(15000); }
                    catch(InterruptedException e1) {}
                }
            }
            if(!connectionsSucceeded) { // All attempts at connecting to db exhausted
		if(debugLevel > 0) {
		    log.println("\r\nAll attempts at connecting to Database exhausted");
		}
                throw new IOException();
            }
        } catch (Exception e) { 
            throw new IOException();
        }
        
        // Fire up the background housekeeping thread

        runner = new Thread(this);
        runner.start();

    }//End DbConnectionBroker()


    /**
     * 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;
	long maxCheckoutMillis = maxCheckoutSeconds * 1000;


        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) {
			if(debugLevel > 1) {
			    log.println("Warnings on connection " + 
					String.valueOf(i) + " " + currSQLWarning);
			}
			connPool[i].clearWarnings();
		    }
		} catch(SQLException e) {
		    if(debugLevel > 1) {
			log.println("Cannot access Warnings: " + e);
		    }
		}
		
	    }
            
	    for(int i=0; i < currConnections; i++) { // Do for each connection
		long age = System.currentTimeMillis() - connCreateDate[i];
		

		try {  // Test the connection with createStatement call
		    synchronized(connStatus) {
			if(connStatus[i] > 0) { // In use, catch it next time!
			    
			    // Check the time it's been checked out and recycle
			    long timeInUse = System.currentTimeMillis() - 
				connLockTime[i];			
			    if(debugLevel > 2) {
				log.println("Warning.  Connection " + i + 
					    " in use for " + timeInUse + 
					    " ms");
			    }
			    if(maxCheckoutMillis != 0) {
				if(timeInUse > maxCheckoutMillis) {
				    if(debugLevel > 1) {
					log.println("Warning. Connection " + 
						    i + " failed to be returned in time.  Recycling...");
				    }
				    throw new SQLException();
				}
			    }
			    
			    continue;
			}
			connStatus[i] = 2; // Take offline (2 indicates housekeeping lock)
		    }
		    
		    
		    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) {

		    if(debugLevel > 1) {
			log.println(new Date().toString() + 
				    " ***** Recycling connection " + 
				    String.valueOf(i) + ":");
		    }
			
		    try {			
			connPool[i].close(); 
		    } catch(SQLException e0) {
			if(debugLevel > 0) {
			    log.println("Error!  Can't close connection!  Might have been closed already.  Trying to recycle anyway... (" + e0 + ")");
			}

⌨️ 快捷键说明

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