public void launch() {
    try {
      testSuiteDir = agent.getTestSuiteDir();
      ensureExistingDirectory(testSuiteDir);

      WorkerType type = workerJvmSettings.getWorkerType();
      int workerIndex = workerJvmSettings.getWorkerIndex();
      LOGGER.info(format("Starting a Java Virtual Machine for %s Worker #%d", type, workerIndex));

      String hzConfigFileName = (type == WorkerType.MEMBER) ? "hazelcast" : "client-hazelcast";
      hzConfigFile = createTmpXmlFile(hzConfigFileName, workerJvmSettings.getHazelcastConfig());
      log4jFile = createTmpXmlFile("worker-log4j", workerJvmSettings.getLog4jConfig());
      LOGGER.info("Spawning Worker JVM using settings: " + workerJvmSettings);

      WorkerJvm worker = startWorkerJvm();
      LOGGER.info(format("Finished starting a JVM for %s Worker #%d", type, workerIndex));

      waitForWorkersStartup(worker, workerJvmSettings.getWorkerStartupTimeout());
    } catch (Exception e) {
      LOGGER.error("Failed to start Worker", e);

      agent.getCoordinatorLogger().fatal("Failed to start Worker: " + e.getMessage());
      throw new SpawnWorkerFailedException("Failed to start Worker", e);
    }
  }
  private String[] buildArgs(WorkerJvm workerJvm, WorkerType type) {
    List<String> args = new LinkedList<String>();

    int workerIndex = workerJvmSettings.getWorkerIndex();
    int workerPort = agent.getPort() + workerIndex;

    addNumaCtlSettings(args);
    addProfilerSettings(workerJvm, args);

    args.add("-classpath");
    args.add(getClasspath());
    args.addAll(getJvmOptions());
    args.add("-XX:OnOutOfMemoryError=\"touch worker.oome\"");
    args.add("-Dhazelcast.logging.type=log4j");
    args.add("-Dlog4j.configuration=file:" + log4jFile.getAbsolutePath());

    args.add("-DSIMULATOR_HOME=" + getSimulatorHome());
    args.add("-DworkerId=" + workerJvm.getId());
    args.add("-DworkerType=" + type);
    args.add("-DpublicAddress=" + agent.getPublicAddress());
    args.add("-DagentIndex=" + agent.getAddressIndex());
    args.add("-DworkerIndex=" + workerIndex);
    args.add("-DworkerPort=" + workerPort);
    args.add("-DautoCreateHzInstance=" + workerJvmSettings.isAutoCreateHzInstance());
    args.add(
        "-DworkerPerformanceMonitorIntervalSeconds="
            + workerJvmSettings.getWorkerPerformanceMonitorIntervalSeconds());
    args.add("-DhzConfigFile=" + hzConfigFile.getAbsolutePath());

    // add class name to start correct worker type
    args.add(type.getClassName());

    return args.toArray(new String[args.size()]);
  }
  private void waitForWorkersStartup(WorkerJvm worker, int workerTimeoutSec) {
    int loopCount =
        (int) TimeUnit.SECONDS.toMillis(workerTimeoutSec) / WAIT_FOR_WORKER_STARTUP_INTERVAL_MILLIS;
    for (int i = 0; i < loopCount; i++) {
      if (hasExited(worker)) {
        throw new SpawnWorkerFailedException(
            format(
                "Startup of Worker on host %s failed, check log files in %s for more information!",
                agent.getPublicAddress(), worker.getWorkerHome()));
      }

      String address = readAddress(worker);
      if (address != null) {
        worker.setHzAddress(address);
        LOGGER.info(format("Worker %s started", worker.getId()));
        return;
      }

      sleepMillis(WAIT_FOR_WORKER_STARTUP_INTERVAL_MILLIS);
    }

    throw new SpawnWorkerFailedException(
        format(
            "Worker %s of Testsuite %s on Agent %s didn't start within %s seconds",
            worker.getId(),
            agent.getTestSuite().getId(),
            agent.getPublicAddress(),
            workerTimeoutSec));
  }
  private WorkerJvm startWorkerJvm() throws IOException {
    int workerIndex = workerJvmSettings.getWorkerIndex();
    WorkerType type = workerJvmSettings.getWorkerType();

    SimulatorAddress workerAddress =
        new SimulatorAddress(AddressLevel.WORKER, agent.getAddressIndex(), workerIndex, 0);
    String workerId =
        "worker-" + agent.getPublicAddress() + '-' + workerIndex + '-' + type.toLowerCase();
    File workerHome = new File(testSuiteDir, workerId);
    ensureExistingDirectory(workerHome);

    WorkerJvm workerJvm = new WorkerJvm(workerAddress, workerId, workerHome);

    generateWorkerStartScript(type, workerJvm);

    ProcessBuilder processBuilder =
        new ProcessBuilder(new String[] {"bash", "worker.sh"})
            .directory(workerHome)
            .redirectErrorStream(true);

    Map<String, String> environment = processBuilder.environment();
    String javaHome = getJavaHome();
    String path = javaHome + File.pathSeparator + "bin:" + environment.get("PATH");
    environment.put("PATH", path);
    environment.put("JAVA_HOME", javaHome);

    Process process = processBuilder.start();
    workerJvm.setProcess(process);
    copyResourcesToWorkerId(workerId);
    workerJvmManager.add(workerAddress, workerJvm);

    return workerJvm;
  }
 private String getClasspath() {
   String hzVersionDirectory =
       directoryForVersionSpec(workerJvmSettings.getHazelcastVersionSpec());
   return CLASSPATH
       + CLASSPATH_SEPARATOR
       + getSimulatorHome()
       + "/hz-lib/"
       + hzVersionDirectory
       + "/*"
       + CLASSPATH_SEPARATOR
       + getSimulatorHome()
       + "/user-lib/*"
       + CLASSPATH_SEPARATOR
       + new File(agent.getTestSuiteDir(), "lib/*").getAbsolutePath();
 }
 private void copyResourcesToWorkerId(String workerId) {
   File workersDir = new File(getSimulatorHome(), "workers");
   String testSuiteId = agent.getTestSuite().getId();
   File uploadDirectory = new File(workersDir, testSuiteId + "/upload/").getAbsoluteFile();
   if (!uploadDirectory.exists() || !uploadDirectory.isDirectory()) {
     LOGGER.debug("Skip copying upload directory to workers since no upload directory was found");
     return;
   }
   String copyCommand =
       format(
           "cp -rfv %s/%s/upload/* %s/%s/%s/",
           workersDir, testSuiteId, workersDir, testSuiteId, workerId);
   execute(copyCommand);
   LOGGER.info(format("Finished copying '%s' to Worker", workersDir));
 }