gt:                 double planTimeAvg = result.getLong("PLAN_TIME_AVG")/ 1000000.0;
context: /* This file is part of VoltDB.
   * Copyright (C) 2008-2017 VoltDB Inc.
   *
   * Permission is hereby granted, free of charge, to any person obtaining
   * a copy of this software and associated documentation files (the
   * "Software"), to deal in the Software without restriction, including
   * without limitation the rights to use, copy, modify, merge, publish,
   * distribute, sublicense, and/or sell copies of the Software, and to
   * permit persons to whom the Software is furnished to do so, subject to
   * the following conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   * OTHER DEALINGS IN THE SOFTWARE.
   */
  
  package adhocbenchmark;
  
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.OutputStreamWriter;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  import java.util.NoSuchElementException;
  import java.util.Random;
  import java.util.Set;
  import java.util.Timer;
  import java.util.TimerTask;
  import java.util.concurrent.CountDownLatch;
  
  import org.voltdb.CLIConfig;
  import org.voltdb.VoltTable;
  import org.voltdb.client.Client;
  import org.voltdb.client.ClientConfig;
  import org.voltdb.client.ClientFactory;
  import org.voltdb.client.ClientResponse;
  import org.voltdb.client.ClientStats;
  import org.voltdb.client.ClientStatsContext;
  import org.voltdb.client.ClientStatusListenerExt;
  import org.voltdb.client.NoConnectionsException;
  import org.voltdb.client.ProcCallException;
  import org.voltdb.client.ProcedureCallback;
  import org.voltdb.compiler.AsyncCompilerAgent;
  
  /**
   * Class providing the entire benchmark implementation and command line main().
   */
  public class Benchmark {
  
      // handy, rather than typing this out several times
      static final String HORIZONTAL_RULE =
              "----------" + "----------" + "----------" + "----------" +
              "----------" + "----------" + "----------" + "----------" + "\n";
  
      // validated command line configuration
      final BenchmarkConfig cliConfig;
      // Reference to the database connection we will use
      final Client client;
      // Timer for periodic stats printing
      Timer timer;
      // Benchmark start time
      long benchmarkStartTS;
  
      final QueryTracer tracer;
  
      // Statistics manager objects from the client
      final ClientStatsContext periodicStatsContext;
      final ClientStatsContext fullStatsContext;
  
      private final class CallProcedureCallback implements ProcedureCallback {
          final String query;
          final long queryIndex;
  
          public CallProcedureCallback(long queryIndex, final String query) {
              this.queryIndex = queryIndex;
              this.query = query;
          }
  
          @Override
          public void clientCallback(ClientResponse clientResponse) throws Exception {
              if (clientResponse.getStatus() != ClientResponse.SUCCESS) {
                  tracer.logQueryFailedAndExit(queryIndex, query, clientResponse);
              }
          }
      }
  
      /**
       * Uses included {@link CLIConfig} class to
       * declaratively state command line options with defaults
       * and validation.
       */
      static class BenchmarkConfig extends CLIConfig {
  
          @Option(desc = "Interval for performance feedback, in seconds.")
          long displayinterval = 5;
  
          @Option(desc = "Comma separated list of the form server[:port] to connect to.")
          String servers = "localhost";
  
          @Option(desc = "Input configuration file path.")
          String configfile = "config.xml";
  
          @Option(desc = "Output file path for raw summary statistics.")
          String statsfile = "";
  
          @Option(desc = "Output file path for query tracing (disabled by default).")
          String querytracefile = "";
  
          @Option(desc = "Benchmark duration in seconds (0=infinite).")
          int duration = 60;
  
          @Option(desc = "Warm-up duration in seconds (0=disable warm-up).")
          int warmup = 5;
  
          @Option(desc = "Maximum # of outstanding transactions (0=not throttled).")
          int querythrottle = AsyncCompilerAgent.MAX_QUEUE_DEPTH;
  
          @Option(desc = "Test to run.")
          String test = BenchmarkConfiguration.getDefaultTestName();
  
          @Override
          public void validate() {
              if (displayinterval <= 0)
                  exitWithMessageAndUsage("displayinterval must be > 0");
              if (duration < 0)
                  exitWithMessageAndUsage("duration must be 0 or a positive integer");
              if (warmup < 0)
                  exitWithMessageAndUsage("warmup must be 0 or a positive integer");
              if (querythrottle < 0)
                  exitWithMessageAndUsage("querythrottle must 0 or a positive integer");
              // We don't know the test names here. Ask for them and use them to validate.
              Set<String> tests = BenchmarkConfiguration.getTestNames();
              test = test.toLowerCase();
              if (!tests.contains(test)) {
                  StringBuilder validTests = new StringBuilder()
                      .append("test '").append(test).append("' is unknown, use one of: {");
                  for (String test : tests) {
                      validTests.append(" ");
                      validTests.append(test);
                  }
                  validTests.append(" }");
                  exitWithMessageAndUsage(validTests.toString());
              }
          }
      }
  
      /**
       * Provides a callback to be notified on node failure.
       * This example only logs the event.
       */
      class StatusListener extends ClientStatusListenerExt {
          @Override
          public void connectionLost(String hostname, int port, int connectionsLeft, DisconnectCause cause) {
              System.out.printf("Connection to %s:%d was closed.\n", hostname, port);
          }
      }
  
      /**
       * Constructor for benchmark instance.
       * Configures VoltDB client and prints configuration.
       *
       * @param cliConfig Parsed & validated CLI options.
       */
      public Benchmark(BenchmarkConfig cliConfig) {
  
          this.cliConfig = cliConfig;
  
          ClientConfig clientConfig = new ClientConfig("", "", new StatusListener());
          // Throttle so that ad hoc queries don't get rejected with "planner not available".
          if (cliConfig.querythrottle > 0) {
              System.out.printf("Throttling maximum outstanding transactions to %d\n",
                                cliConfig.querythrottle);
              clientConfig.setMaxOutstandingTxns(cliConfig.querythrottle);
          }
          client = ClientFactory.createClient(clientConfig);
  
          periodicStatsContext = client.createStatsContext();
          fullStatsContext = client.createStatsContext();
  
          tracer = new QueryTracer(cliConfig.querytracefile);
  
          System.out.print(HORIZONTAL_RULE);
          System.out.println(" Command Line Configuration");
          System.out.println(HORIZONTAL_RULE);
          System.out.println(cliConfig.getConfigDumpString());
  
  
      }
  
      /**
       * Connect to a single server with retry. Limited exponential backoff.
       * No timeout. This will run until the process is killed if it's not
       * able to connect.
       *
       * @param server hostname:port or just hostname (hostname can be ip).
       */
      void connectToOneServerWithRetry(String server) {
          int sleep = 1000;
          while (true) {
              try {
                  client.createConnection(server);
                  break;
              }
              catch (Exception e) {
                  System.err.printf("Connection failed - retrying in %d second(s).\n", sleep / 1000);
                  try { Thread.sleep(sleep); } catch (Exception interruted) {}
                  if (sleep < 8000) sleep += sleep;
              }
          }
          System.out.printf("Connected to VoltDB node at: %s.\n", server);
      }
  
      /**
       * Connect to a set of servers in parallel. Each will retry until
       * connection. This call will block until all have connected.
       *
       * @param servers A comma separated list of servers using the hostname:port
       * syntax (where :port is optional).
       * @throws InterruptedException if anything bad happens with the threads.
       */
      void connect(String servers) throws InterruptedException {
          System.out.println("Connecting to VoltDB...");
  
          String[] serverArray = servers.split(",");
          final CountDownLatch connections = new CountDownLatch(serverArray.length);
  
          // use a new thread to connect to each server
          for (final String server : serverArray) {
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      connectToOneServerWithRetry(server);
                      connections.countDown();
                  }
              }).start();
          }
          // block until all have connected
          connections.await();
      }
  
      /**
       * Create a Timer task to display performance data every displayInterval seconds
       */
      public void schedulePeriodicStats() {
          timer = new Timer();
          TimerTask statsPrinting = new TimerTask() {
              @Override
              public void run() { printStatistics(); }
          };
          timer.scheduleAtFixedRate(statsPrinting,
                                    cliConfig.displayinterval * 1000,
                                    cliConfig.displayinterval * 1000);
      }
  
      /**
       * Prints a one line update on performance that can be printed
       * periodically during a benchmark.
       */
      public synchronized void printStatistics() {
          ClientStats stats = periodicStatsContext.fetchAndResetBaseline().getStats();
          long time = Math.round((stats.getEndTimestamp() - benchmarkStartTS) / 1000.0);
  
          System.out.printf("%02d:%02d:%02d ", time / 3600, (time / 60) % 60, time % 60);
          System.out.printf("Throughput %d/s, ", stats.getTxnThroughput());
          System.out.printf("Txns Completed %d ", stats.getInvocationsCompleted());
          System.out.printf("Avg/95%% Latency %.2f/%.2fms\n", stats.getAverageLatency(),
                  stats.kPercentileLatencyAsDouble(0.95));
          System.out.println("");
      }
  
      /**
       * Prints the results and statistics about performance.
       * @throws IOException
       *
       * @throws Exception if anything unexpected happens.
       */
      public synchronized void printResults(long totalElapsedMS, long queryElapsedMS) throws IOException {
          ClientStats stats = fullStatsContext.fetch().getStats();
  
          // 1. Results and performance statistics
          System.out.print(HORIZONTAL_RULE);
          System.out.println(" Results");
          System.out.println(HORIZONTAL_RULE);
          System.out.printf("Total queries completed:       %9d\n", stats.getInvocationsCompleted());
  
          // 2. Performance statistics
          System.out.print(HORIZONTAL_RULE);
          System.out.println(" Client Workload Statistics");
          System.out.println(HORIZONTAL_RULE);
  
          System.out.printf("Average throughput:            %,9d txns/sec\n", stats.getTxnThroughput());
          System.out.printf("Average latency:               %,9.2f ms\n", stats.getAverageLatency());
          System.out.printf("95th percentile latency:       %,9.2f ms\n", stats.kPercentileLatencyAsDouble(.95));
          System.out.printf("99th percentile latency:       %,9.2f ms\n", stats.kPercentileLatencyAsDouble(.99));
  
          System.out.print("\n" + HORIZONTAL_RULE);
          System.out.println(" System Server Statistics");
          System.out.println(HORIZONTAL_RULE);
  
          System.out.printf("Reported Internal Avg Latency: %,9.2f ms\n", stats.getAverageInternalLatency());
  
          System.out.print("\n" + HORIZONTAL_RULE);
          System.out.println(" Planner Statistics");
          System.out.println(HORIZONTAL_RULE);
  
          printPlannerStatistics();
  
          // 3. Write stats to file if requested
          client.writeSummaryCSV(stats, cliConfig.statsfile);
      }
  
      /**
       * Print planner and cache statistics.
       * @throws IOException
       * @throws NoConnectionsException
       */
      public void printPlannerStatistics() throws IOException, NoConnectionsException {
          try {
              VoltTable result = client.callProcedure("@Statistics", "PLANNER", 0).getResults()[0];
              while(result.advanceRow()) {
                  String hostname  = result.getString("HOSTNAME");
                  long siteId      = result.getLong("SITE_ID");
                  long partitionId = result.getLong("PARTITION_ID");
                  long hits1       = result.getLong("CACHE1_HITS");
                  long hits2       = result.getLong("CACHE2_HITS");
                  long level1      = result.getLong("CACHE1_LEVEL");
                  long level2      = result.getLong("CACHE2_LEVEL");
                  long misses      = result.getLong("CACHE_MISSES");
                  long total       = hits1 + hits2 + misses;
                  double hitpc1    = (100.0 * hits1) / total;
                  double hitpc2    = (100.0 * hits2) / total;
                  double planTimeMin = result.getLong("PLAN_TIME_MIN")/ 1000000.0;
                  double planTimeMax = result.getLong("PLAN_TIME_MAX")/ 1000000.0;
  