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

📄 simpledatasource.java

📁 本套系统采用了业界当前最为流行的beanAction组件
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
   */
  public long getAverageRequestTime() {
    synchronized (POOL_LOCK) {
      return requestCount == 0 ? 0 : accumulatedRequestTime / requestCount;
    }
  }

  /**
   * Getter for the average time spent waiting for connections that were in use
   * @return The average time
   */
  public long getAverageWaitTime() {
    synchronized (POOL_LOCK) {
      return hadToWaitCount == 0 ? 0 : accumulatedWaitTime / hadToWaitCount;
    }
  }

  /**
   * Getter for the number of requests that had to wait for connections that were in use
   * @return The number of requests that had to wait
   */
  public long getHadToWaitCount() {
    synchronized (POOL_LOCK) {
      return hadToWaitCount;
    }
  }

  /**
   * Getter for the number of invalid connections that were found in the pool
   * @return The number of invalid connections
   */
  public long getBadConnectionCount() {
    synchronized (POOL_LOCK) {
      return badConnectionCount;
    }
  }

  /**
   * Getter for the number of connections that were claimed before they were returned
   * @return The number of connections
   */
  public long getClaimedOverdueConnectionCount() {
    synchronized (POOL_LOCK) {
      return claimedOverdueConnectionCount;
    }
  }

  /**
   * Getter for the average age of overdue connections
   * @return The average age
   */
  public long getAverageOverdueCheckoutTime() {
    synchronized (POOL_LOCK) {
      return claimedOverdueConnectionCount == 0 ? 0 : accumulatedCheckoutTimeOfOverdueConnections / claimedOverdueConnectionCount;
    }
  }


  /**
   * Getter for the average age of a connection checkout
   * @return The average age
   */
  public long getAverageCheckoutTime() {
    synchronized (POOL_LOCK) {
      return requestCount == 0 ? 0 : accumulatedCheckoutTime / requestCount;
    }
  }

  /**
   * Returns the status of the connection pool
   * @return The status
   */
  public String getStatus() {
    StringBuffer buffer = new StringBuffer();

    buffer.append("\n===============================================================");
    buffer.append("\n jdbcDriver                     ").append(jdbcDriver);
    buffer.append("\n jdbcUrl                        ").append(jdbcUrl);
    buffer.append("\n jdbcUsername                   ").append(jdbcUsername);
    buffer.append("\n jdbcPassword                   ").append((jdbcPassword == null ? "NULL" : "************"));
    buffer.append("\n poolMaxActiveConnections       ").append(poolMaximumActiveConnections);
    buffer.append("\n poolMaxIdleConnections         ").append(poolMaximumIdleConnections);
    buffer.append("\n poolMaxCheckoutTime            " + poolMaximumCheckoutTime);
    buffer.append("\n poolTimeToWait                 " + poolTimeToWait);
    buffer.append("\n poolPingEnabled                " + poolPingEnabled);
    buffer.append("\n poolPingQuery                  " + poolPingQuery);
    buffer.append("\n poolPingConnectionsOlderThan   " + poolPingConnectionsOlderThan);
    buffer.append("\n poolPingConnectionsNotUsedFor  " + poolPingConnectionsNotUsedFor);
    buffer.append("\n --------------------------------------------------------------");
    buffer.append("\n activeConnections              " + activeConnections.size());
    buffer.append("\n idleConnections                " + idleConnections.size());
    buffer.append("\n requestCount                   " + getRequestCount());
    buffer.append("\n averageRequestTime             " + getAverageRequestTime());
    buffer.append("\n averageCheckoutTime            " + getAverageCheckoutTime());
    buffer.append("\n claimedOverdue                 " + getClaimedOverdueConnectionCount());
    buffer.append("\n averageOverdueCheckoutTime     " + getAverageOverdueCheckoutTime());
    buffer.append("\n hadToWait                      " + getHadToWaitCount());
    buffer.append("\n averageWaitTime                " + getAverageWaitTime());
    buffer.append("\n badConnectionCount             " + getBadConnectionCount());
    buffer.append("\n===============================================================");
    return buffer.toString();
  }

  /**
   * Closes all of the connections in the pool
   */
  public void forceCloseAll() {
    synchronized (POOL_LOCK) {
      for (int i = activeConnections.size(); i > 0; i--) {
        try {
          SimplePooledConnection conn = (SimplePooledConnection) activeConnections.remove(i - 1);
          conn.invalidate();

          Connection realConn = conn.getRealConnection();
          if (!realConn.getAutoCommit()) {
            realConn.rollback();
          }
          realConn.close();
        } catch (Exception e) {
          // ignore
        }
      }
      for (int i = idleConnections.size(); i > 0; i--) {
        try {
          SimplePooledConnection conn = (SimplePooledConnection) idleConnections.remove(i - 1);
          conn.invalidate();

          Connection realConn = conn.getRealConnection();
          if (!realConn.getAutoCommit()) {
            realConn.rollback();
          }
          realConn.close();
        } catch (Exception e) {
          // ignore
        }
      }
    }
    if (log.isDebugEnabled()) {
      log.debug("SimpleDataSource forcefully closed/removed all connections.");
    }
  }

  private void pushConnection(SimplePooledConnection conn)
      throws SQLException {

    synchronized (POOL_LOCK) {
      activeConnections.remove(conn);
      if (conn.isValid()) {
        if (idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == getExpectedConnectionTypeCode()) {
          accumulatedCheckoutTime += conn.getCheckoutTime();
          if (!conn.getRealConnection().getAutoCommit()) {
            conn.getRealConnection().rollback();
          }
          SimplePooledConnection newConn = new SimplePooledConnection(conn.getRealConnection(), this);
          idleConnections.add(newConn);
          newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
          newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
          conn.invalidate();
          if (log.isDebugEnabled()) {
            log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
          }
          POOL_LOCK.notifyAll();
        } else {
          accumulatedCheckoutTime += conn.getCheckoutTime();
          if (!conn.getRealConnection().getAutoCommit()) {
            conn.getRealConnection().rollback();
          }
          conn.getRealConnection().close();
          if (log.isDebugEnabled()) {
            log.debug("Closed connection " + conn.getRealHashCode() + ".");
          }
          conn.invalidate();
        }
      } else {
        if (log.isDebugEnabled()) {
          log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
        }
        badConnectionCount++;
      }
    }
  }

  private SimplePooledConnection popConnection(String username, String password)
      throws SQLException {
    boolean countedWait = false;
    SimplePooledConnection conn = null;
    long t = System.currentTimeMillis();
    int localBadConnectionCount = 0;

    while (conn == null) {
      synchronized (POOL_LOCK) {
        if (idleConnections.size() > 0) {
          // Pool has available connection
          conn = (SimplePooledConnection) idleConnections.remove(0);
          if (log.isDebugEnabled()) {
            log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
          }
        } else {
          // Pool does not have available connection
          if (activeConnections.size() < poolMaximumActiveConnections) {
            // Can create new connection
            if (useDriverProps) {
              conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, driverProps), this);
            } else {
              conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword), this);
            }
            Connection realConn = conn.getRealConnection();
            if (realConn.getAutoCommit() != jdbcDefaultAutoCommit) {
              realConn.setAutoCommit(jdbcDefaultAutoCommit);
            }
            if (log.isDebugEnabled()) {
              log.debug("Created connection " + conn.getRealHashCode() + ".");
            }
          } else {
            // Cannot create new connection
            SimplePooledConnection oldestActiveConnection = (SimplePooledConnection) activeConnections.get(0);
            long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
            if (longestCheckoutTime > poolMaximumCheckoutTime) {
              // Can claim overdue connection
              claimedOverdueConnectionCount++;
              accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
              accumulatedCheckoutTime += longestCheckoutTime;
              activeConnections.remove(oldestActiveConnection);
              if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
                oldestActiveConnection.getRealConnection().rollback();
              }
              conn = new SimplePooledConnection(oldestActiveConnection.getRealConnection(), this);
              oldestActiveConnection.invalidate();
              if (log.isDebugEnabled()) {
                log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
              }
            } else {
              // Must wait
              try {
                if (!countedWait) {
                  hadToWaitCount++;
                  countedWait = true;
                }
                if (log.isDebugEnabled()) {
                  log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
                }
                long wt = System.currentTimeMillis();
                POOL_LOCK.wait(poolTimeToWait);
                accumulatedWaitTime += System.currentTimeMillis() - wt;
              } catch (InterruptedException e) {
                break;
              }
            }
          }
        }
        if (conn != null) {
          if (conn.isValid()) {
            if (!conn.getRealConnection().getAutoCommit()) {
              conn.getRealConnection().rollback();
            }
            conn.setConnectionTypeCode(assembleConnectionTypeCode(jdbcUrl, username, password));
            conn.setCheckoutTimestamp(System.currentTimeMillis());
            conn.setLastUsedTimestamp(System.currentTimeMillis());
            activeConnections.add(conn);
            requestCount++;
            accumulatedRequestTime += System.currentTimeMillis() - t;
          } else {
            if (log.isDebugEnabled()) {
              log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
            }
            badConnectionCount++;
            localBadConnectionCount++;
            conn = null;
            if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
              if (log.isDebugEnabled()) {
                log.debug("SimpleDataSource: Could not get a good connection to the database.");
              }
              throw new SQLException("SimpleDataSource: Could not get a good connection to the database.");
            }
          }
        }
      }

    }

    if (conn == null) {
      if (log.isDebugEnabled()) {
        log.debug("SimpleDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
      }
      throw new SQLException("SimpleDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
    }

    return conn;
  }

  /**
   * Method to check to see if a connection is still usable
   *
   * @param conn - the connection to check
   * @return True if the connection is still usable
   */
  private boolean pingConnection(SimplePooledConnection conn) {
    boolean result = true;

    try {
      result = !conn.getRealConnection().isClosed();
    } catch (SQLException e) {
      if (log.isDebugEnabled()) {
        log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
      }    	
      result = false;
    }

    if (result) {
      if (poolPingEnabled) {
        if ((poolPingConnectionsOlderThan > 0 && conn.getAge() > poolPingConnectionsOlderThan)
            || (poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor)) {

          try {
            if (log.isDebugEnabled()) {
              log.debug("Testing connection " + conn.getRealHashCode() + " ...");
            }
            Connection realConn = conn.getRealConnection();
            Statement statement = realConn.createStatement();
            ResultSet rs = statement.executeQuery(poolPingQuery);
            rs.close();
            statement.close();
            if (!realConn.getAutoCommit()) {
              realConn.rollback();
            }
            result = true;
            if (log.isDebugEnabled()) {
              log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
            }
          } catch (Exception e) {
            log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());          	
            try {
              conn.getRealConnection().close();
            } catch (Exception e2) {
              //ignore
            }
            result = false;
            if (log.isDebugEnabled()) {
              log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
            }
          }
        }
      }
    }
    return result;
  }

  /**
   * Unwraps a pooled connection to get to the 'real' connection
   *
   * @param conn - the pooled connection to unwrap
   * @return The 'real' connection
   */
  public static Connection unwrapConnection(Connection conn) {
    if (conn instanceof SimplePooledConnection) {
      return ((SimplePooledConnection) conn).getRealConnection();
    } else {
      return conn;
    }
  }

  protected void finalize() throws Throwable {
    forceCloseAll();
  }

  /**
   * ---------------------------------------------------------------------------------------
   * SimplePooledConnection
   * ---------------------------------------------------------------------------------------
   */
  private static class SimplePooledConnection implements InvocationHandler {

    private static final String CLOSE = "close";
    private static final Class[] IFACES = new Class[]{Connection.class};

⌨️ 快捷键说明

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