this.partition.getPoolWatchThreadSignalQueue().take(); maxNewConnections = this.partition.getMaxConnections()-this.partition.getCreatedConnections(); while (maxNewConnections == 0 || (this.partition.getAvailableConnections() *100/this.partition.getMaxConnections() > this.poolAvailabilityThreshold)){ if (maxNewConnections == 0){ this.partition.setUnableToCreateMoreTransactions(true); this.partition.getPoolWatchThreadSignalQueue().take(); maxNewConnections = this.partition.getMaxConnections()-this.partition.getCreatedConnections(); fillConnections(Math.min(maxNewConnections, this.partition.getAcquireIncrement())); if (this.partition.getCreatedConnections() < this.partition.getMinConnections()){ fillConnections(this.partition.getMinConnections() - this.partition.getCreatedConnections() );
/** * Tests if this partition has hit a threshold and signal to the pool watch thread to create new connections * * @param connectionPartition to test for. */ protected void maybeSignalForMoreConnections(ConnectionPartition connectionPartition) { if (!connectionPartition.isUnableToCreateMoreTransactions() && !this.poolShuttingDown && connectionPartition.getAvailableConnections() * 100 / connectionPartition.getMaxConnections() <= this.poolAvailabilityThreshold) { connectionPartition.getPoolWatchThreadSignalQueue().offer(new Object()); // item being pushed is not important. } }
/** Return total number of connections currently in use by an application * @return no of leased connections */ public int getTotalLeased(){ int total=0; for (int i=0; i < this.partitionCount && this.partitions[i] != null; i++){ total+=this.partitions[i].getCreatedConnections()-this.partitions[i].getAvailableConnections(); } return total; }
ConnectionPartition connectionPartition = new ConnectionPartition(this); this.partitions[p] = connectionPartition; BlockingQueue<ConnectionHandle> connectionHandles = new LinkedBlockingQueue<>(this.config .getMaxConnectionsPerPartition()); this.partitions[p].setFreeConnections(connectionHandles); this.partitions[p].addFreeConnection(new ConnectionHandle(null, this.partitions[p], this, false));
@Override public String toString() { return Objects.toStringHelper(this) .add("url", this.pool.getConfig().getJdbcUrl()) .add("user", this.pool.getConfig().getUsername()) .add("minConnections", this.getMinConnections()) .add("maxConnections", this.getMaxConnections()) .add("acquireIncrement", this.acquireIncrement) .add("createdConnections", this.createdConnections) .add("freeConnections", this.getFreeConnections()) .toString(); } }
/** Update counters and call hooks. * @param handle connection handle. */ protected void postDestroyConnection(ConnectionHandle handle){ ConnectionPartition partition = handle.getOriginatingPartition(); if (this.finalizableRefQueue != null && handle.getInternalConnection() != null){ //safety this.finalizableRefs.remove(handle.getInternalConnection()); // assert o != null : "Did not manage to remove connection from finalizable ref queue"; } partition.updateCreatedConnections(-1); partition.setUnableToCreateMoreTransactions(false); // we can create new ones now, this is an optimization // "Destroying" for us means: don't put it back in the pool. if (handle.getConnectionHook() != null){ handle.getConnectionHook().onDestroy(handle); } }
long nextCheckInMs = this.maxAgeInMs; int partitionSize= this.partition.getAvailableConnections(); long currentTime = System.currentTimeMillis(); for (int i=0; i < partitionSize; i++){ try { connection = this.partition.getFreeConnections().poll(); if (!(connection.getOriginatingPartition().getFreeConnections().offer(connection))){ connection.internalClose();
/** Closes off all connections in all partitions. */ public void terminateAllConnections(){ this.terminationLock.lock(); try{ // close off all connections. for (int i=0; i < this.pool.partitionCount; i++) { this.pool.partitions[i].setUnableToCreateMoreTransactions(false); // we can create new ones now, this is an optimization List<ConnectionHandle> clist = new LinkedList<ConnectionHandle>(); this.pool.partitions[i].getFreeConnections().drainTo(clist); for (ConnectionHandle c: clist){ this.pool.destroyConnection(c); } } } finally { this.terminationLock.unlock(); } }
@Override public ConnectionHandle pollConnection(){ ConnectionHandle result = null; int partition = (int) (Thread.currentThread().getId() % this.pool.partitionCount); ConnectionPartition connectionPartition = this.pool.partitions[partition]; result = connectionPartition.getFreeConnections().poll(); if (result == null) { // we ran out of space on this partition, pick another free one for (int i=0; i < this.pool.partitionCount; i++){ if (i == partition) { continue; // we already determined it's not here } result = this.pool.partitions[i].getFreeConnections().poll(); // try our luck with this partition if (result != null) { connectionPartition = this.pool.partitions[i]; // we found it here break; // we found a connection } } } if (!connectionPartition.isUnableToCreateMoreTransactions()){ // unless we can't create any more connections... this.pool.maybeSignalForMoreConnections(connectionPartition); // see if we need to create more } return result; }
@Override protected Connection getConnectionInternal() throws SQLException { ConnectionHandle result = pollConnection(); // we still didn't find an empty one, wait forever (or as per config) until our partition is free if (result == null) { int partition = (int) (Thread.currentThread().getId() % this.pool.partitionCount); ConnectionPartition connectionPartition = this.pool.partitions[partition]; try { result = connectionPartition.getFreeConnections().poll(this.pool.connectionTimeoutInMs, TimeUnit.MILLISECONDS); if (result == null){ if (this.pool.nullOnConnectionTimeout){ return null; } // 08001 = The application requester is unable to establish the connection. throw new SQLException("Timed out waiting for a free available connection.", "08001"); } } catch (InterruptedException e) { if (this.pool.nullOnConnectionTimeout){ return null; } throw PoolUtil.generateSQLException(e.getMessage(), e); } } return result; }
/** * Return total number of connections created in all partitions. * * @return number of created connections */ public int getTotalCreatedConnections(){ int total=0; for (int i=0; i < this.partitionCount && this.partitions[i] != null; i++){ total+=this.partitions[i].getCreatedConnections(); } return total; }
/** Return the number of free connections available to an application right away (excluding connections that can be * created dynamically) * @return number of free connections */ public int getTotalFree(){ int total=0; for (int i=0; i < this.partitionCount && this.partitions[i] != null ; i++){ total+=this.partitions[i].getAvailableConnections(); } return total; }
/** Closes off this connection * @param connection to close */ protected void closeConnection(ConnectionHandle connection) { if (connection != null && !connection.isClosed()) { try { connection.internalClose(); } catch (SQLException e) { logger.error("Destroy connection exception", e); } finally { this.pool.postDestroyConnection(connection); connection.getOriginatingPartition().getPoolWatchThreadSignalQueue().offer(new Object()); // item being pushed is not important. } } }
/** Adds new connections to the partition. * @param connectionsToCreate number of connections to create * @throws InterruptedException */ private void fillConnections(int connectionsToCreate) throws InterruptedException { try { for (int i=0; i < connectionsToCreate; i++){ // boolean dbDown = this.pool.getDbIsDown().get(); if (this.pool.poolShuttingDown){ break; } this.partition.addFreeConnection(new ConnectionHandle(null, this.partition, this.pool, false)); } } catch (Exception e) { logger.error("Error in trying to obtain a connection. Retrying in "+this.acquireRetryDelayInMs+"ms", e); Thread.sleep(this.acquireRetryDelayInMs); } }
ConnectionPartition connectionPartition = new ConnectionPartition(this); this.partitions[p]=connectionPartition; BlockingQueue<ConnectionHandle> connectionHandles = new LinkedBlockingQueue<ConnectionHandle>(this.config.getMaxConnectionsPerPartition()); this.partitions[p].setFreeConnections(connectionHandles); this.partitions[p].addFreeConnection(new ConnectionHandle(null, this.partitions[p], this, false));
/** * Return total number of connections currently in use by an application * * @return no of leased connections */ public int getTotalLeased() { int total = 0; for (int i = 0; i < this.partitionCount && this.partitions[i] != null; i++) { total += this.partitions[i].getCreatedConnections() - this.partitions[i].getAvailableConnections(); } return total; }
/** * Update counters and call hooks. * * @param handle connection handle. */ protected void postDestroyConnection(ConnectionHandle handle) { ConnectionPartition partition = handle.getOriginatingPartition(); if (this.finalizableRefQueue != null && handle.getInternalConnection() != null) { //safety check this.finalizableRefs.remove(handle.getInternalConnection()); // o != null : "Did not manage to remove connection from finalizable ref queue"; } partition.updateCreatedConnections(-1); // we can create new ones now, this is an optimization partition.setUnableToCreateMoreTransactions(false); // "Destroying" for us means: don't put it back in the pool. if (handle.getConnectionHook() != null) { handle.getConnectionHook().onDestroy(handle); } }
int partitionSize= this.partition.getAvailableConnections(); long currentTimeInMs = System.currentTimeMillis(); connection = this.partition.getFreeConnections().poll(); if (connection != null){ connection.setOriginatingPartition(this.partition); if (!(connection.getOriginatingPartition().getFreeConnections().offer(connection))){ connection.internalClose();
/** Places a connection back in the originating partition. * @param connectionHandle to place back * @throws SQLException on error */ protected void putConnectionBackInPartition(ConnectionHandle connectionHandle) throws SQLException { if (this.cachedPoolStrategy && ((CachedConnectionStrategy)this.connectionStrategy).tlConnections.dumbGet().getValue()){ connectionHandle.logicallyClosed.set(true); ((CachedConnectionStrategy)this.connectionStrategy).tlConnections.set(new AbstractMap.SimpleEntry<ConnectionHandle, Boolean>(connectionHandle, false)); } else { BlockingQueue<ConnectionHandle> queue = connectionHandle.getOriginatingPartition().getFreeConnections(); if (!queue.offer(connectionHandle)){ // this shouldn't fail connectionHandle.internalClose(); } } }
/** * Return total number of connections created in all partitions. * * @return number of created connections */ public int getTotalCreatedConnections() { int total = 0; for (int i = 0; i < this.partitionCount && this.partitions[i] != null; i++) { total += this.partitions[i].getCreatedConnections(); } return total; }