GEODE-8838: Provide some ability to launch ChildVM with specific port for RemoteDUnitVM stub (#5909)
- This change is intended to address an issue with port bind conflicts
specifically when VMs are restarted. Thus this change only specifies a
specific port when bouncing a VM. In this case we use a RMI port
outside the usual range of ephemeral ports for MacOS (49152–65535) and
Linux (32768-60999).
- We typically try and use ephemeral ports everywhere. However,
sometimes an ephemeral port created during a prior start needs to be
used as a fixed port on subsequent bounces. In this case, ephemeral
ports that are allocated early may end up conflicting with these fixed
ports.
- Remove various unused methods related to bounce()ing VMs.
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/DUnitEnv.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/DUnitEnv.java
index cdb5c59..76c7852 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/DUnitEnv.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/DUnitEnv.java
@@ -15,10 +15,8 @@
package org.apache.geode.test.dunit;
import java.io.File;
-import java.rmi.RemoteException;
import java.util.Properties;
-import org.apache.geode.test.dunit.internal.BounceResult;
/**
* This class provides an abstraction over the environment that is used to run dunit. This will
@@ -61,9 +59,6 @@
public abstract int getId();
- public abstract BounceResult bounce(String version, int pid, boolean force)
- throws RemoteException;
-
public abstract File getWorkingDirectory(int pid);
public abstract File getWorkingDirectory(String version, int pid);
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
index 5d99ddb..0c5baf5 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
@@ -33,6 +33,7 @@
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.Logger;
+import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.process.ProcessUtils;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.test.dunit.internal.ChildVMLauncher;
@@ -584,7 +585,14 @@
executeMethodOnObject(runnable, "run", new Object[0]);
}
processHolder.waitFor();
- processHolder = childVMLauncher.launchVM(targetVersion, id, true);
+
+ // We typically try and use ephemeral ports everywhere. However, sometimes an ephemeral port
+ // created during a prior start needs to be used as a fixed port on subsequent bounces. In
+ // this case, ephemeral ports that are allocated early may end up conflicting with these
+ // fixed ports. So when we bounce a VM, use an RMI port outside the usual range of ephemeral
+ // ports for MacOS (49152–65535) and Linux (32768-60999).
+ int remoteStubPort = AvailablePortHelper.getRandomAvailableTCPPort();
+ processHolder = childVMLauncher.launchVM(targetVersion, id, true, remoteStubPort);
version = targetVersion;
client = childVMLauncher.getStub(id);
available = true;
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVM.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVM.java
index ddd9a8e..6c5297d 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVM.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVM.java
@@ -41,6 +41,7 @@
try {
int namingPort = Integer.getInteger(DUnitLauncher.RMI_PORT_PARAM);
int vmNum = Integer.getInteger(DUnitLauncher.VM_NUM_PARAM);
+ int remoteStubPort = Integer.getInteger(DUnitLauncher.REMOTE_STUB_PORT_PARAM, 0);
String geodeVersion = System.getProperty(DUnitLauncher.VM_VERSION_PARAM);
int pid = OSProcess.getId();
logger.info("VM" + vmNum + " is launching" + (pid > 0 ? " with PID " + pid : ""));
@@ -52,7 +53,7 @@
.lookup("//localhost:" + namingPort + "/" + DUnitLauncher.MASTER_PARAM);
DUnitLauncher.init(holder);
DUnitLauncher.locatorPort = holder.getLocatorPort();
- final RemoteDUnitVM dunitVM = new RemoteDUnitVM();
+ final RemoteDUnitVM dunitVM = new RemoteDUnitVM(remoteStubPort);
final String name = "//localhost:" + namingPort + "/vm" + vmNum;
Naming.rebind(name, dunitVM);
JUnit4DistributedTestCase.initializeBlackboard();
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVMLauncher.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVMLauncher.java
index a161bd5..e2d5c4a 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVMLauncher.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ChildVMLauncher.java
@@ -20,7 +20,7 @@
public interface ChildVMLauncher {
- ProcessHolder launchVM(String version, int vmNum, boolean bouncedVM)
+ ProcessHolder launchVM(String version, int vmNum, boolean bouncedVM, int remoteStubPort)
throws IOException;
RemoteDUnitVMIF getStub(int i) throws RemoteException, NotBoundException, InterruptedException;
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitHost.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitHost.java
index 4695358..02ef017 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitHost.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitHost.java
@@ -32,7 +32,7 @@
DUnitHost(String hostName, ProcessManager processManager, VMEventNotifier vmEventNotifier)
throws RemoteException {
super(hostName, vmEventNotifier);
- this.debuggingVM = new VM(this, VersionManager.CURRENT_VERSION, -1, new RemoteDUnitVM(), null,
+ this.debuggingVM = new VM(this, VersionManager.CURRENT_VERSION, -1, new RemoteDUnitVM(0), null,
null);
this.processManager = processManager;
this.vmEventNotifier = vmEventNotifier;
@@ -104,7 +104,7 @@
}
// now create the one we really want
- processManager.launchVM(version, n, false);
+ processManager.launchVM(version, n, false, 0);
processManager.waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);
addVM(n, version, processManager.getStub(n), processManager.getProcessHolder(n),
processManager);
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitLauncher.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitLauncher.java
index 69cbd97..9a14733 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitLauncher.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitLauncher.java
@@ -118,6 +118,7 @@
static final String MASTER_PARAM = "DUNIT_MASTER";
+ public static final String REMOTE_STUB_PORT_PARAM = "DUnitLauncher.REMOTE_STUB_PORT";
public static final String RMI_PORT_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.RMI_PORT";
public static final String RMI_HOST_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.RMI_HOST";
public static final String VM_NUM_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.VM_NUM";
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/Master.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/Master.java
index fde4a90..a97c433 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/Master.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/Master.java
@@ -14,13 +14,10 @@
*/
package org.apache.geode.test.dunit.internal;
-import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
-import org.apache.geode.test.dunit.VM;
-import org.apache.geode.test.version.VersionManager;
public class Master extends UnicastRemoteObject implements MasterRemote {
private static final long serialVersionUID = 1178600200232603119L;
@@ -49,26 +46,4 @@
// do nothing
}
- @Override
- public BounceResult bounce(int pid) {
- return bounce(VersionManager.CURRENT_VERSION, pid, false);
- }
-
- @Override
- public BounceResult bounce(String version, int pid, boolean force) {
- processManager.bounce(version, pid, force);
-
- try {
- if (!processManager.waitForVMs(DUnitLauncher.STARTUP_TIMEOUT)) {
- throw new RuntimeException(DUnitLauncher.STARTUP_TIMEOUT_MESSAGE);
- }
- RemoteDUnitVMIF remote =
- (RemoteDUnitVMIF) registry.lookup(VM.getVMName(VersionManager.CURRENT_VERSION, pid));
- return new BounceResult(pid, remote);
- } catch (RemoteException | NotBoundException e) {
- throw new RuntimeException("could not lookup name", e);
- } catch (InterruptedException e) {
- throw new RuntimeException("Failed waiting for VM", e);
- }
- }
}
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/MasterRemote.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/MasterRemote.java
index f613f7e..38bc17a 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/MasterRemote.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/MasterRemote.java
@@ -25,7 +25,4 @@
void ping() throws RemoteException;
- BounceResult bounce(int pid) throws RemoteException;
-
- BounceResult bounce(String version, int pid, boolean force) throws RemoteException;
}
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ProcessManager.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ProcessManager.java
index 209c822..c9c04e4 100755
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ProcessManager.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/ProcessManager.java
@@ -60,12 +60,12 @@
}
public synchronized void launchVM(int vmNum) throws IOException {
- launchVM(VersionManager.CURRENT_VERSION, vmNum, false);
+ launchVM(VersionManager.CURRENT_VERSION, vmNum, false, 0);
}
@Override
- public synchronized ProcessHolder launchVM(String version, int vmNum, boolean bouncedVM)
- throws IOException {
+ public synchronized ProcessHolder launchVM(String version, int vmNum, boolean bouncedVM,
+ int remoteStubPort) throws IOException {
if (bouncedVM) {
processes.remove(vmNum);
}
@@ -88,7 +88,7 @@
workingDir.mkdirs();
}
- String[] cmd = buildJavaCommand(vmNum, namingPort, version);
+ String[] cmd = buildJavaCommand(vmNum, namingPort, version, remoteStubPort);
System.out.println("Executing " + Arrays.toString(cmd));
if (log4jConfig != null) {
@@ -141,26 +141,6 @@
return false;
}
- @Deprecated
- public synchronized void bounce(String version, int vmNum, boolean force) {
- if (!processes.containsKey(vmNum)) {
- throw new IllegalStateException("No such process " + vmNum);
- }
- try {
- ProcessHolder holder = processes.remove(vmNum);
- if (force) {
- holder.killForcibly();
- } else {
- holder.kill();
- }
- holder.waitFor();
- System.out.println("Old process for vm_" + vmNum + " has exited");
- launchVM(version, vmNum, true);
- } catch (InterruptedException | IOException e) {
- throw new RuntimeException("Unable to restart VM " + vmNum, e);
- }
- }
-
private void linkStreams(final String version, final int vmNum, final ProcessHolder holder,
final InputStream in, final PrintStream out) {
final String vmName = "[" + VM.getVMName(version, vmNum) + "] ";
@@ -246,7 +226,7 @@
return classpath;
}
- private String[] buildJavaCommand(int vmNum, int namingPort, String version) {
+ private String[] buildJavaCommand(int vmNum, int namingPort, String version, int remoteStubPort) {
String cmd = System.getProperty("java.home") + File.separator
+ "bin" + File.separator + "java";
String dunitClasspath = System.getProperty("java.class.path");
@@ -280,6 +260,7 @@
String jreLib = separator + "jre" + separator + "lib" + separator;
classPath = removeFromPath(classPath, jreLib);
cmds.add(classPath);
+ cmds.add("-D" + DUnitLauncher.REMOTE_STUB_PORT_PARAM + "=" + remoteStubPort);
cmds.add("-D" + DUnitLauncher.RMI_PORT_PARAM + "=" + namingPort);
cmds.add("-D" + DUnitLauncher.VM_NUM_PARAM + "=" + vmNum);
cmds.add("-D" + DUnitLauncher.VM_VERSION_PARAM + "=" + version);
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/RemoteDUnitVM.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/RemoteDUnitVM.java
index 49473cb..3033d15 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/RemoteDUnitVM.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/RemoteDUnitVM.java
@@ -26,8 +26,8 @@
class RemoteDUnitVM extends UnicastRemoteObject implements RemoteDUnitVMIF {
private static final Logger logger = LogService.getLogger();
- RemoteDUnitVM() throws RemoteException {
- // super
+ RemoteDUnitVM(int port) throws RemoteException {
+ super(port);
}
/**
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/StandAloneDUnitEnv.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/StandAloneDUnitEnv.java
index ee6542b..0ebd2e7 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/StandAloneDUnitEnv.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/StandAloneDUnitEnv.java
@@ -15,7 +15,6 @@
package org.apache.geode.test.dunit.internal;
import java.io.File;
-import java.rmi.RemoteException;
import java.util.Properties;
import org.apache.geode.test.dunit.DUnitEnv;
@@ -55,11 +54,6 @@
}
@Override
- public BounceResult bounce(String version, int pid, boolean force) throws RemoteException {
- return master.bounce(version, pid, force);
- }
-
- @Override
public File getWorkingDirectory(int pid) {
return getWorkingDirectory(VersionManager.CURRENT_VERSION, pid);
}