Bug 567221: Improve configuration of detection of lost clients
- Add support to disable detection of lost clients
- Improve spec of timings in JMPoolTest
Change-Id: Id5d2599c730bc0f0116b06367753b22692ad808d
diff --git a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/AbstractServiTest.java b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/AbstractServiTest.java
index 04cf27e..02401cf 100644
--- a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/AbstractServiTest.java
+++ b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/AbstractServiTest.java
@@ -160,11 +160,16 @@
}
- protected void assertNodeOperative(final RServi servi) throws StatusException, UnexpectedRDataException {
- final ProgressMonitor m= new NullProgressMonitor();
+ protected void assertNodeOperative(final RServi servi,
+ final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
final int i= this.testInt++;
final RObject result= servi.evalData(i + "L + 1L", m);
assertEquals(i + 1, RDataUtils.checkSingleIntValue(result));
}
+ protected void assertNodeOperative(
+ final RServi servi) throws StatusException, UnexpectedRDataException {
+ assertNodeOperative(servi, new NullProgressMonitor());
+ }
+
}
diff --git a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
index b4efd31..67732ef 100644
--- a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
+++ b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
@@ -22,7 +22,7 @@
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullLateInit;
-import static org.eclipse.statet.internal.rj.servi.APool2.CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY;
+import static org.eclipse.statet.internal.rj.servi.APool2.CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY;
import java.util.ArrayList;
import java.util.List;
@@ -63,9 +63,9 @@
public class JMPoolTest extends AbstractServiTest {
- private static int NODE_STARTUP_MILLIS= 7000;
+ private static int NODE_STARTUP_MILLIS= 7_000;
- private static int WAIT_IDLE_SEC= 30;
+ private static int WAIT_IDLE_MILLIS= 30_000;
private static List<JMPoolServer> allServers= new ArrayList<>();
private static @Nullable JMPoolServer sharedServer;
@@ -234,7 +234,7 @@
assertNodeOperative(servi1);
assertNodeOperative(servi2);
- Thread.sleep(WAIT_IDLE_SEC);
+ Thread.sleep(WAIT_IDLE_MILLIS);
assertIdleCount(0);
closeServi(servi1);
@@ -277,7 +277,8 @@
@Test
public void UsageCount_borrowMax() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
+ final ProgressMonitor m1= new NullProgressMonitor();
+ final ProgressMonitor m2= new NullProgressMonitor();
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(1);
@@ -286,13 +287,13 @@
this.server.start();
final RServi servi1= getServi("test1");
- assertNodeOperative(servi1);
- final int pid1= RDataUtils.checkSingleIntValue(servi1.evalData("Sys.getpid()", m));
+ assertNodeOperative(servi1, m1);
+ final int pid1= RDataUtils.checkSingleIntValue(servi1.evalData("Sys.getpid()", m1));
closeServi(servi1);
final RServi servi2= getServi("test2");
- assertNodeOperative(servi2);
- final int pid2= RDataUtils.checkSingleIntValue(servi2.evalData("Sys.getpid()", m));
+ assertNodeOperative(servi2, m2);
+ final int pid2= RDataUtils.checkSingleIntValue(servi2.evalData("Sys.getpid()", m2));
assertTrue(pid1 != pid2);
@@ -302,10 +303,9 @@
@Test
public void ClientCheck_alive() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
- final int intervalSec= 10;
- System.setProperty(CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY,
- Long.toString(TimeUnit.SECONDS.toMillis(intervalSec)) );
+ final int periodMillis= 15_000;
+ System.setProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY,
+ Integer.toString(periodMillis) );
try {
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(1);
@@ -319,22 +319,21 @@
final PoolNodeObject node1= assertSinglePoolNode();
awaitStateCondition(node1, (state) -> (state != PoolNodeState.ALLOCATED),
- (int)(2.5 * intervalSec) + WAIT_IDLE_SEC );
+ (int)(1.2 * periodMillis) + WAIT_IDLE_MILLIS );
skipChecking(node1);
assertEquals(PoolNodeState.ALLOCATED, node1.getState());
assertNodeOperative(servi1);
}
finally {
- System.clearProperty(CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY);
+ System.clearProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY);
}
}
@Test
public void ClientCheck_dead() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
- final int intervalSec= 10;
- System.setProperty(CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY,
- Long.toString(TimeUnit.SECONDS.toMillis(intervalSec)) );
+ final int periodMillis= 15_000;
+ System.setProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY,
+ Integer.toString(periodMillis) );
try {
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(1);
@@ -353,21 +352,47 @@
clientCheckJob.cancel(false);
awaitStateCondition(node1, (state) -> (state != PoolNodeState.ALLOCATED),
- (int)(2.5 * intervalSec) + WAIT_IDLE_SEC );
+ (int)(1.2 * periodMillis) + WAIT_IDLE_MILLIS );
skipChecking(node1);
assertEquals(PoolNodeState.DISPOSED, node1.getState());
Assertions.assertThrows(StatusException.class, () -> assertNodeOperative(servi1));
}
finally {
- System.clearProperty(CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY);
+ System.clearProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY);
+ }
+ }
+
+ @Test
+ public void ClientCheck_disabled() throws Exception {
+ System.setProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY, "-1");
+ try {
+ final PoolConfig poolConfig= new PoolConfig();
+ poolConfig.setMaxTotalCount(1);
+ poolConfig.setMaxUsageCount(1);
+ this.server.setPoolConfig(poolConfig);
+ this.server.start();
+
+ final RServi servi1= getServi("test1");
+ assertNodeOperative(servi1);
+
+// final PoolNodeObject node1= assertSinglePoolNode();
+//
+// awaitStateCondition(node1, (state) -> (state != PoolNodeState.ALLOCATED),
+// (int)(1.2 * APool2.CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_DEFAULT_VALUE) + WAIT_IDLE_MILLIS );
+// skipChecking(node1);
+// assertEquals(PoolNodeState.ALLOCATED, node1.getState());
+// assertNodeOperative(servi1);
+
+ closeServi(servi1);
+ }
+ finally {
+ System.clearProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY);
}
}
@Test
public void PoolNode_getState() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
-
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(1);
poolConfig.setMinIdleCount(1);
@@ -392,8 +417,6 @@
@Test
public void PoolNode_getClientLabel() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
-
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(1);
poolConfig.setMinIdleCount(1);
@@ -415,8 +438,6 @@
@Test
public void Bug570660() throws Exception {
- final ProgressMonitor m= new NullProgressMonitor();
-
final PoolConfig poolConfig= new PoolConfig();
poolConfig.setMaxTotalCount(2);
poolConfig.setMinIdleCount(2);
@@ -443,7 +464,7 @@
if (expected == poolStatus.getNumIdling()) {
return;
}
- if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - t) > WAIT_IDLE_SEC) {
+ if (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t) > WAIT_IDLE_MILLIS) {
assertEquals(expected, poolStatus.getNumIdling(), "num idle");
}
Thread.sleep(100);
@@ -451,17 +472,17 @@
}
private void skipChecking(final PoolNodeObject node) throws InterruptedException {
- awaitStateCondition(node, (state) -> (state != PoolNodeState.CHECKING), WAIT_IDLE_SEC);
+ awaitStateCondition(node, (state) -> (state != PoolNodeState.CHECKING), WAIT_IDLE_MILLIS);
}
private void awaitStateCondition(final PoolNodeObject node,
- final Predicate<PoolNodeState> condition, final int timeoutSec) throws InterruptedException {
+ final Predicate<PoolNodeState> condition, final int timeoutMillis) throws InterruptedException {
final long t= System.nanoTime();
while (true) {
if (condition.test(node.getState())) {
return;
}
- if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - t) > timeoutSec) {
+ if (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t) > timeoutMillis) {
return;
}
Thread.sleep(100);
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
index c148fdc..d0c2633 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2.java
@@ -25,6 +25,7 @@
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.rj.RjInvalidConfigurationException;
import org.eclipse.statet.rj.servi.pool.PoolConfig;
@@ -32,7 +33,10 @@
public class APool2 extends GenericObjectPool<APool2NodeHandler> {
- public static final String CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY= "org.eclipse.statet.rj.servi.pool.ClientCheck.Interval.millis"; //$NON-NLS-1$
+ public static final String CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY= "org.eclipse.statet.rj.servi.pool.client.AllocationRenewPeriod.millis"; //$NON-NLS-1$
+
+ public static final int CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_DEFAULT_VALUE= 600_000; // 10 min
+ private static final int CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE= 5_000;
private static final byte CLOSING= 2;
@@ -78,19 +82,18 @@
private final APool2NodeFactory factory;
- private int clientCheckIntervalMillis;
+ private int clientAllocationRenewPeriodMillis;
private volatile byte state;
private boolean evicting;
private final Object stateLock= new Object();
- public APool2(final String id, final APool2NodeFactory factory, final PoolConfig config) {
+ public APool2(final String id, final APool2NodeFactory factory, final PoolConfig config)
+ throws RjInvalidConfigurationException {
super(factory, createAConfig(config));
this.id= id;
- { final String s= System.getProperty(CLIENT_CHECK_INTERVAL_MILLIS_PROPERTY_KEY);
- this.clientCheckIntervalMillis= (s != null) ? Integer.parseInt(s) : 60000;
- }
+ this.clientAllocationRenewPeriodMillis= getClientAllocationRenewPeriodMillisDefaultValue();
factory.setPool(this);
this.factory= factory;
@@ -114,8 +117,26 @@
return super.getMaxIdle();
}
- public int getClientCheckIntervalMillis() {
- return this.clientCheckIntervalMillis;
+ protected int getClientAllocationRenewPeriodMillisDefaultValue() throws RjInvalidConfigurationException {
+ try {
+ int millis= CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_DEFAULT_VALUE;
+ final String s= System.getProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY);
+ if (s != null) {
+ millis= Integer.parseInt(s);
+ }
+ if (millis != -1 && millis < CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE) {
+ throw new IllegalArgumentException(String.format("%1$s < %2$s",
+ this.clientAllocationRenewPeriodMillis, CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE ));
+ }
+ return millis;
+ }
+ catch (final Exception e) {
+ throw new RjInvalidConfigurationException("AllocationRenewPeriod.millis: " + e.getMessage());
+ }
+ }
+
+ public int getClientAllocationRenewPeriodMillis() {
+ return this.clientAllocationRenewPeriodMillis;
}
diff --git a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
index 7de6298..5646f15 100644
--- a/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
+++ b/servi/org.eclipse.statet.rj.servi/srcServiPool/org/eclipse/statet/internal/rj/servi/APool2NodeHandler.java
@@ -57,8 +57,8 @@
private volatile long accessId= -1;
- private int checkInterval;
- private long checkTimestamp;
+ private int allocationRenewPeriodMillis;
+ private long allocationRenewTimestamp;
public APool2NodeHandler(final APool2 pool) {
@@ -137,8 +137,8 @@
super.bindClient(name, host);
synchronized (this) {
this.accessId= this.p.getBorrowedCount();
- this.checkInterval= this.pool.getClientCheckIntervalMillis();
- this.checkTimestamp= System.nanoTime();
+ this.allocationRenewPeriodMillis= this.pool.getClientAllocationRenewPeriodMillis();
+ this.allocationRenewTimestamp= System.nanoTime();
}
}
@@ -191,7 +191,9 @@
@Override
public int getCheckIntervalMillis() throws RemoteException {
- return this.checkInterval;
+ final int allocationRenewPeriodMillis;
+ return ((allocationRenewPeriodMillis= this.allocationRenewPeriodMillis) != -1) ?
+ (int)(allocationRenewPeriodMillis / 2.125) - 1000 : -1;
}
@Override
@@ -199,19 +201,24 @@
if (this.accessId != accessId) {
throw new RjClosedException("RServi instance is no longer valid.");
}
- this.checkTimestamp= System.nanoTime();
+ this.allocationRenewTimestamp= System.nanoTime();
}
void checkClientLost(final long nanos) {
- if (this.accessId == -1
- || nanos - this.checkTimestamp < (long)(2.1 * this.checkInterval + 1000) * 1_000_000
- || getPooledObject().getState() == PooledObjectState.INVALID ) {
- return;
+ { final int allocationRenewPeriodMillis;
+ if (this.accessId == -1
+ || (allocationRenewPeriodMillis= this.allocationRenewPeriodMillis) == -1
+ || nanos - this.allocationRenewTimestamp < allocationRenewPeriodMillis * 1_000_000L
+ || getPooledObject().getState() == PooledObjectState.INVALID ) {
+ return;
+ }
}
String clientLabel;
synchronized (this) {
+ final int allocationRenewPeriodMillis;
if (this.accessId == -1
- || nanos - this.checkTimestamp < (long)(2.1 * this.checkInterval + 1000) * 1_000_000 ) {
+ || (allocationRenewPeriodMillis= this.allocationRenewPeriodMillis) == -1
+ || nanos - this.allocationRenewTimestamp < allocationRenewPeriodMillis * 1_000_000L ) {
return;
}
clientLabel= getClientLabel();