fix bug that messes up the max usage count when the entries' max usage counter overflows

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2020-11-30 17:01:09 +01:00
parent df3a32601a
commit 0ff1bfdd5e
2 changed files with 27 additions and 1 deletions

View File

@ -449,6 +449,12 @@ public class Pool<T> implements AutoCloseable, Dumpable
this.state = new AtomicBiInteger(Integer.MIN_VALUE, 0);
}
// for testing only
void setUsageCount(int usageCount)
{
this.state.getAndSetHi(usageCount);
}
/** Enable a reserved entry {@link Entry}.
* An entry returned from the {@link #reserve(int)} method must be enabled with this method,
* once and only once, before it is usable by the pool.
@ -527,7 +533,9 @@ public class Pool<T> implements AutoCloseable, Dumpable
if (closed || multiplexingCount >= maxMultiplex || (currentMaxUsageCount > 0 && usageCount >= currentMaxUsageCount))
return false;
if (state.compareAndSet(encoded, usageCount + 1, multiplexingCount + 1))
// Prevent overflowing the usage counter by capping it at Integer.MAX_VALUE.
int newUsageCount = usageCount == Integer.MAX_VALUE ? Integer.MAX_VALUE : usageCount + 1;
if (state.compareAndSet(encoded, newUsageCount, multiplexingCount + 1))
return true;
}
}

View File

@ -554,6 +554,24 @@ public class PoolTest
assertThat(e1.getUsageCount(), is(2));
}
@ParameterizedTest
@MethodSource(value = "strategy")
public void testDynamicMaxUsageCountChangeOverflowMaxInt(Factory factory)
{
Pool<String> pool = factory.getPool(1);
Pool<String>.Entry entry = pool.reserve(-1);
entry.enable("aaa", false);
entry.setUsageCount(Integer.MAX_VALUE);
Pool<String>.Entry acquired1 = pool.acquire();
assertThat(acquired1, notNullValue());
assertThat(pool.release(acquired1), is(true));
pool.setMaxUsageCount(1);
Pool<String>.Entry acquired2 = pool.acquire();
assertThat(acquired2, nullValue());
}
@Test
public void testConfigLimits()
{