diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/SimplePool.java b/spring-integration-core/src/main/java/org/springframework/integration/util/SimplePool.java index 98239e328c9..010038cf943 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/SimplePool.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/SimplePool.java @@ -36,6 +36,7 @@ * demand up to the limit. * * @author Gary Russell + * @author Sergey Bogatyrev * @since 2.2 * */ @@ -102,11 +103,9 @@ public synchronized void setPoolSize(int poolSize) { break; } T item = this.available.poll(); - if (item == null) { - this.permits.release(); - break; + if (item != null) { + doRemoveItem(item); } - doRemoveItem(item); this.poolSize.decrementAndGet(); delta++; } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/util/SimplePoolTests.java b/spring-integration-core/src/test/java/org/springframework/integration/util/SimplePoolTests.java index 3f6945bbe64..e4482ce3619 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/util/SimplePoolTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/util/SimplePoolTests.java @@ -19,7 +19,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; @@ -30,6 +32,7 @@ /** * @author Gary Russell + * @author Sergey Bogatyrev * @since 2.2 * */ @@ -147,6 +150,72 @@ public void testDoubleReturn() { assertThat(permits.availablePermits()).isEqualTo(2); } + @Test + public void testSizeUpdateIfNotAllocated() { + SimplePool pool = stringPool(10, new HashSet<>(), new AtomicBoolean()); + pool.setWaitTimeout(0); + pool.setPoolSize(5); + assertThat(pool.getPoolSize()).isEqualTo(5); + + // allocating all available items to check permits + Set allocatedItems = new HashSet<>(); + for (int i = 0; i < 5; i++) { + allocatedItems.add(pool.getItem()); + } + assertThat(allocatedItems).hasSize(5); + + // no more items can be allocated (indirect check of permits) + try { + pool.getItem(); + fail("No more items should be allocated"); + } + catch (PoolItemNotAvailableException e) { + // permits state correctly + } + } + + @Test + public void testSizeUpdateIfAllocated() { + SimplePool pool = stringPool(10, new HashSet<>(), new AtomicBoolean()); + pool.setWaitTimeout(0); + List allocated = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + allocated.add(pool.getItem()); + } + + // release only 2 items + for (int i = 0; i < 2; i++) { + pool.releaseItem(allocated.get(i)); + } + + // trying to reduce pool size + pool.setPoolSize(5); + + // at this moment the actual pool size can be reduced only partially, because + // only 2 items have been released, so 8 items are in use + assertThat(pool.getPoolSize()).isEqualTo(8); + assertThat(pool.getAllocatedCount()).isEqualTo(8); + assertThat(pool.getIdleCount()).isEqualTo(0); + + // releasing 3 items + for (int i = 2; i < 5; i++) { + pool.releaseItem(allocated.get(i)); + } + + // now pool size should be reduced + assertThat(pool.getPoolSize()).isEqualTo(5); + assertThat(pool.getAllocatedCount()).isEqualTo(5); + assertThat(pool.getIdleCount()).isEqualTo(0); + + // no more items can be allocated (indirect check of permits) + try { + pool.getItem(); + fail("No more items should be allocated"); + } + catch (PoolItemNotAvailableException e) { + // permits state correctly + } + } private SimplePool stringPool(int size, final Set strings, final AtomicBoolean stale) {