Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix deadlock and couple more problems in
DefaultConnectionPool
(#699)
This commit fixes three problems in `DefaultConnectionPool`/`ConcurrentPool`: - deadlock in `DefaultConnectionPool`; - unnecessary and harmful removal from `OpenConcurrencyLimiter.desiredConnectionSlots`; - double release in `DefaultConnectionPool`/`ConcurrentPool`. Deadlock in `DefaultConnectionPool` a) Before introducing OpenConcurrencyLimiter, "AsyncGetter" thread was used only to do blocking `ConcurrentPool.get`. b) After, I started to additionally use "AsyncGetter" to do blocking `OpenConcurrencyLimiter.waitUntilOpenPermitAvailable`. As a result, we may have a thread that gets the last connection (`maxSize` is reached) from `ConcurrentPool` and submits `waitUntilOpenPermitAvailable` to "AsyncGetter". Concurrently with this happening, the "AsyncGetter" tries to get from `ConcurrentPool` and is blocked because there are no more connections available. In such an execution, `waitUntilOpenPermitAvailable` cannot be completed by "AsyncGetter" because "AsyncGetter" is blocked doing a different task, which itself cannot be completed. A solution is to do `ConcurrentPool.get` and `waitUntilOpenPermitAvailable` in different threads. This way these two different kinds of tasks will not block each other by waiting in the same queue to be done by a single thread. Potential unnecessary and harmful removal from `OpenConcurrencyLimiter.desiredConnectionSlots` If `acquirePermitOrGetAvailableOpenedConnection` is called with `true` as `tryGetAvailable`, and `getPooledConnectionImmediately` throws an exception, then `expressDesireToGetAvailableConnection` is not called but `giveUpOnTryingToGetAvailableConnection` is still called, which is incorrect. Double release in `DefaultConnectionPool`/`ConcurrentPool` On one hand `ConcurrentPool.ensureMinSize` tries to not require the caller to do what can be done by the method itself, e.g., it releases the connection to the pool itself. On the other hand, always releasing in `ensureMinSize` may lead to releasing a permit for the same connection twice, thus not respecting the `maxSize`. It is not easy (requires an additional knob and logic) to prevent the caller (`DefaultConnectionPool`) from releasing a connection when initialization fails. It is, therefore, seems better to mandate that the caller releases a connection if initialization fails. JAVA-3927
- Loading branch information
Showing
4 changed files
with
126 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.