blob: b377cc34fbd5af64714c284a37bf035a3e27d894 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geode.perftest.jvms;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD;
import static org.apache.geode.perftest.jvms.JavaVersion.v17;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.geode.perftest.infrastructure.Infrastructure;
import org.apache.geode.perftest.jvms.rmi.ChildJVM;
class JVMLauncher {
private static final Logger logger = LoggerFactory.getLogger(RemoteJVMFactory.class);
public static final String WITH_STRACE = "benchmark.withStrace";
JVMLauncher() {}
CompletableFuture<Void> launchProcesses(Infrastructure infra, int rmiPort,
List<JVMMapping> mapping)
throws UnknownHostException {
List<CompletableFuture<Void>> futures = new ArrayList<CompletableFuture<Void>>();
for (JVMMapping entry : mapping) {
CompletableFuture<Void> future = launchWorker(infra, rmiPort, entry);
futures.add(future);
}
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
CompletableFuture<Void> launchWorker(Infrastructure infra, int rmiPort,
JVMMapping jvmConfig)
throws UnknownHostException {
final String[] shellCommand = traceCommand(
buildCommand(InetAddress.getLocalHost().getHostAddress(), rmiPort, jvmConfig), jvmConfig);
CompletableFuture<Void> future = new CompletableFuture<>();
Thread thread = new Thread("Worker " + jvmConfig.getNode().getAddress()) {
public void run() {
try {
infra.onNode(jvmConfig.getNode(), new String[] {"rm", "-rf", jvmConfig.getOutputDir()});
infra.onNode(jvmConfig.getNode(), new String[] {"mkdir", "-p", jvmConfig.getOutputDir()});
int result = infra.onNode(jvmConfig.getNode(), shellCommand);
if (result != 0) {
logger.error("ChildJVM exited with error code " + result);
}
} catch (Throwable t) {
logger.error("Launching " + String.join(" ", shellCommand) + " on " + jvmConfig.getNode()
+ "Failed.", t);
} finally {
future.complete(null);
}
}
};
thread.start();
return future;
}
String[] traceCommand(final String[] command, JVMMapping jvmConfig) {
List<String> strace = new ArrayList<>();
if (Boolean.getBoolean(WITH_STRACE)) {
strace.add("strace");
strace.add("-o");
strace.add(jvmConfig.getOutputDir() + "/java.strace");
strace.add("-ttt");
strace.add("-T");
strace.add("-f");
strace.add("-ff");
}
strace.addAll(Arrays.asList(command));
return strace.toArray(new String[0]);
}
String[] buildCommand(String rmiHost, int rmiPort, JVMMapping jvmConfig) {
final JavaVersion javaVersion = JavaVersion.current();
List<String> command = new ArrayList<>();
command.add(System.getProperty("java.home") + "/bin/java");
if (javaVersion.atLeast(v17)) {
command.add("@" + jvmConfig.getLibDir() + "/java.args");
}
command.add("-classpath");
command.add(jvmConfig.getLibDir() + "/*");
command.add("-Djava.library.path=" + System.getProperty("user.home") + "/META-INF/native");
command.add("-D" + RemoteJVMFactory.RMI_HOST + "=" + rmiHost);
command.add("-D" + RemoteJVMFactory.RMI_PORT_PROPERTY + "=" + rmiPort);
command.add("-D" + RemoteJVMFactory.JVM_ID + "=" + jvmConfig.getId());
command.add("-D" + RemoteJVMFactory.ROLE + "=" + jvmConfig.getRole());
command.add("-D" + RemoteJVMFactory.OUTPUT_DIR + "=" + jvmConfig.getOutputDir());
if (jvmConfig.getJvmArgs().contains("-Dbenchmark.withSsl=true")) {
command
.add("-Dgemfire." + SSL_KEYSTORE + "=" + jvmConfig.getLibDir() + "/temp-self-signed.jks");
command.add("-Dgemfire." + SSL_KEYSTORE_PASSWORD + "=123456");
command.add(
"-Dgemfire." + SSL_TRUSTSTORE + "=" + jvmConfig.getLibDir() + "/temp-self-signed.jks");
command.add("-Dgemfire." + SSL_TRUSTSTORE_PASSWORD + "=123456");
}
command.addAll(replaceTokens(jvmConfig.getJvmArgs(), jvmConfig));
command.add(ChildJVM.class.getName());
return command.toArray(new String[0]);
}
private static final List<String> replaceTokens(List<String> args, JVMMapping jvmConfig) {
List<String> replaced = new ArrayList<>(args.size());
for (String arg : args) {
replaced.add(replaceTokens(arg, jvmConfig));
}
return replaced;
}
private static String replaceTokens(String arg, JVMMapping jvmConfig) {
arg = arg.replace("OUTPUT_DIR", jvmConfig.getOutputDir());
arg = arg.replace("JVM_ROLE", jvmConfig.getRole());
arg = arg.replace("JVM_ID", Integer.toString(jvmConfig.getId()));
return arg;
}
}