[POOL-347] borrowObject waits for maxWaitMillis over in pool full. Closes #10.
Project: http://git-wip-us.apache.org/repos/asf/commons-pool/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-pool/commit/3e02523b Tree: http://git-wip-us.apache.org/repos/asf/commons-pool/tree/3e02523b Diff: http://git-wip-us.apache.org/repos/asf/commons-pool/diff/3e02523b Branch: refs/heads/release Commit: 3e02523b6907fb22f3582544fe362c785821bcb8 Parents: 2183114 Author: Shunsuke Nakamura <sunsuk...@gmail.com> Authored: Sun Jul 22 08:41:14 2018 -0600 Committer: Gary Gregory <garydgreg...@gmail.com> Committed: Sun Jul 22 08:41:14 2018 -0600 ---------------------------------------------------------------------- src/changes/changes.xml | 3 ++ .../commons/pool2/impl/GenericObjectPool.java | 12 +++++- .../pool2/impl/TestGenericObjectPool.java | 42 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-pool/blob/3e02523b/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fb3d301..bee05d3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,9 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" issue="POOL-346" type="update" due-to="Michael Chen"> Move common configuration setter to BaseGenericObjectPool #9. </action> + <action dev="ggregory" issue="POOL-347" type=fix" due-to="Shunsuke Nakamura"> + borrowObject waits for maxWaitMillis over in pool full. + </action> </release> <release version="2.6.0" date="2018-07-06" description="This is a maintenance release."> <action dev="ggregory" issue="POOL-336" type="update" due-to="Wolfgang Glas"> http://git-wip-us.apache.org/repos/asf/commons-pool/blob/3e02523b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java index 7ad8a5a..a05038a 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java +++ b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java @@ -822,6 +822,9 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> localMaxTotal = Integer.MAX_VALUE; } + long localStartTimeMillis = System.currentTimeMillis(); + long localMaxWaitTimeMillis = Math.max(getMaxWaitMillis(), 0); + // Flag that indicates if create should: // - TRUE: call the factory to create an object // - FALSE: return null @@ -845,7 +848,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> // bring the pool to capacity. Those calls might also // fail so wait until they complete and then re-test if // the pool is at capacity or not. - makeObjectCountLock.wait(); + makeObjectCountLock.wait(localMaxWaitTimeMillis); } } else { // The pool is not at capacity. Create a new object. @@ -853,6 +856,13 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> create = Boolean.TRUE; } } + + // Do not block more if maxWaitTimeMillis is set. + if (create == null && + (localMaxWaitTimeMillis > 0 && + System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) { + create = Boolean.FALSE; + } } if (!create.booleanValue()) { http://git-wip-us.apache.org/repos/asf/commons-pool/blob/3e02523b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java index baac885..b84924d 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java +++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java @@ -2637,6 +2637,48 @@ public class TestGenericObjectPool extends TestBaseObjectPool { } } + @Test(timeout = 1200 /* maxWaitMillis x2 + padding */) + public void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception { + long maxWaitMillis = 500; + + final GenericObjectPool<String> createSlowObjectFactoryPool + = new GenericObjectPool<>(createSlowObjectFactory(60000)); + createSlowObjectFactoryPool.setMaxTotal(1); + createSlowObjectFactoryPool.setMaxWaitMillis(maxWaitMillis); + + // thread1 tries creating a slow object to make pool full. + final WaitingTestThread thread1 = new WaitingTestThread(createSlowObjectFactoryPool, 0); + thread1.start(); + + // Wait for thread1's reaching to create(). + Thread.sleep(100); + + // another one tries borrowObject. It should return within maxWaitMillis. + try { + createSlowObjectFactoryPool.borrowObject(maxWaitMillis); + fail("borrowObject must fail due to timeout by maxWaitMillis"); + } catch (NoSuchElementException e) { + } + + Assert.assertTrue(thread1.isAlive()); + } + + private BasePooledObjectFactory<String> createSlowObjectFactory(final long elapsedTimeMillis) { + return new BasePooledObjectFactory<String>() { + @Override + public String create() throws Exception { + Thread.sleep(elapsedTimeMillis); + return "created"; + } + + @Override + public PooledObject<String> wrap(final String obj) { + // fake + return new DefaultPooledObject<String>(obj); + } + }; + } + @Test public void testErrorFactoryDoesNotBlockThreads() throws Exception {