GEODE-6458: add profiler argument support (#65)

* Added profiler argument support.

* take profile snapshot on jvm close and copy snapshot with benchmark results

Signed-off-by: Jacob Barrett <jbarrett@pivotal.io>

* More string replacements.

* remove dependency on StringUtil since Geode may not have that

Signed-off-by: Helena A. Bales <hbales@pivotal.io>

* GEODE-6458: add options for profiler

add options to run with a profiler, attached to all members.

Signed-off-by: Sean Goller <sgoller@pivotal.io>
diff --git a/geode-benchmarks/build.gradle b/geode-benchmarks/build.gradle
index 8858295..bc6f097 100644
--- a/geode-benchmarks/build.gradle
+++ b/geode-benchmarks/build.gradle
@@ -69,6 +69,7 @@
     systemProperty 'TEST_HOSTS', project.findProperty('hosts')
     systemProperty 'TEST_METADATA', project.findProperty('metadata')
     systemProperty 'OUTPUT_DIR', outputDir
+    systemProperty 'benchmark.profiler.argument', project.findProperty('benchmark.profiler.argument')
 
     doFirst {
         if(!project.hasProperty('hosts')) {
diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/topology/ClientServerTopology.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/topology/ClientServerTopology.java
index 4471dbf..3a30106 100644
--- a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/topology/ClientServerTopology.java
+++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/topology/ClientServerTopology.java
@@ -19,6 +19,8 @@
 import static org.apache.geode.benchmark.topology.ClientServerTopology.Roles.LOCATOR;
 import static org.apache.geode.benchmark.topology.ClientServerTopology.Roles.SERVER;
 
+import org.bouncycastle.util.Arrays;
+
 import org.apache.geode.benchmark.tasks.StartClient;
 import org.apache.geode.benchmark.tasks.StartLocator;
 import org.apache.geode.benchmark.tasks.StartServer;
@@ -49,12 +51,21 @@
     testConfig.role(SERVER, NUM_SERVERS);
     testConfig.role(CLIENT, NUM_CLIENTS);
 
-    testConfig.jvmArgs(CLIENT, JVM_ARGS);
-    testConfig.jvmArgs(LOCATOR, JVM_ARGS);
-    testConfig.jvmArgs(SERVER, JVM_ARGS);
+    String profilerArgument = System.getProperty("benchmark.profiler.argument");
+    testConfig.jvmArgs(CLIENT, appendIfNotEmpty(JVM_ARGS, profilerArgument));
+    testConfig.jvmArgs(LOCATOR, appendIfNotEmpty(JVM_ARGS, profilerArgument));
+    testConfig.jvmArgs(SERVER, appendIfNotEmpty(JVM_ARGS, profilerArgument));
 
     testConfig.before(new StartLocator(LOCATOR_PORT), LOCATOR);
     testConfig.before(new StartServer(LOCATOR_PORT), SERVER);
     testConfig.before(new StartClient(LOCATOR_PORT), CLIENT);
   }
+
+  private static final String[] appendIfNotEmpty(String[] a, String b) {
+    if (null == b || b.length() == 0) {
+      return a;
+    }
+
+    return Arrays.append(a, b);
+  }
 }
diff --git a/gradle/dependency-versions.properties b/gradle/dependency-versions.properties
index e906204..c0fe3d2 100644
--- a/gradle/dependency-versions.properties
+++ b/gradle/dependency-versions.properties
@@ -17,7 +17,7 @@
 junit-jupiter-api.version = 5.3.2
 junit-jupiter-engine.version = 5.3.2
 junit-pioneer.version = 0.3.0
-geode-core.version = 1.7.0
+geode-core.version = 1.8.0
 slf4j-simple.version = 1.7.25
 sshj.version = 0.26.0
 commons-io.version = 2.6
diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java
index 077c2e4..286f495 100644
--- a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java
+++ b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java
@@ -86,9 +86,24 @@
     command.add("-D" + RemoteJVMFactory.JVM_ID + "=" + jvmConfig.getId());
     command.add("-D" + RemoteJVMFactory.OUTPUT_DIR + "=" + jvmConfig.getOutputDir());
     command.add("-Xloggc:" + jvmConfig.getOutputDir() + "/gc.log");
-    command.addAll(jvmConfig.getJvmArgs());
+    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;
+  }
 }
diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java
index 337e6ed..d464ed9 100644
--- a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java
+++ b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java
@@ -69,6 +69,15 @@
     infra.close();
   }
 
+  public void closeController() throws IOException, ExecutionException, InterruptedException {
+    controller.close();
+    exited.get();
+  }
+
+  public void closeInfra() throws IOException, InterruptedException {
+    infra.close();
+  }
+
   /**
    * Copy results to the provided output directory
    */
diff --git a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java
index 04e324b..c231caf 100644
--- a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java
+++ b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java
@@ -123,8 +123,8 @@
 
     logger.info("Lauching JVMs...");
     // launch JVMs in parallel, hook them up
-    try (RemoteJVMs remoteJVMs = remoteJvmFactory.launch(roles, jvmArgs)) {
-
+    RemoteJVMs remoteJVMs = remoteJvmFactory.launch(roles, jvmArgs);
+    try {
       logger.info("Starting before tasks...");
       runTasks(config.getBefore(), remoteJVMs);
 
@@ -133,11 +133,16 @@
 
       logger.info("Starting after tasks...");
       runTasks(config.getAfter(), remoteJVMs);
+    } finally {
+      // Close before copy otherwise logs, stats, and profiles are incomplete or missing.
+      remoteJVMs.closeController();
 
       logger.info("Copying results...");
       remoteJVMs.copyResults(benchmarkOutput);
 
+      remoteJVMs.closeInfra();
     }
+
   }
 
   private void runTasks(List<TestConfig.TestStep> steps,