public ScheduledExecutorService startThreads(
      CommitLog commitLog, final List<CommitlogExecutor> threads) {
    stop = false;
    for (int ii = 0; ii < NUM_THREADS; ii++) {
      final CommitlogExecutor t = new CommitlogExecutor(commitLog);
      threads.add(t);
      t.start();
    }

    final long start = System.currentTimeMillis();
    Runnable printRunnable =
        new Runnable() {
          long lastUpdate = 0;

          public void run() {
            Runtime runtime = Runtime.getRuntime();
            long maxMemory = mb(runtime.maxMemory());
            long allocatedMemory = mb(runtime.totalMemory());
            long freeMemory = mb(runtime.freeMemory());
            long temp = 0;
            long sz = 0;
            for (CommitlogExecutor cle : threads) {
              temp += cle.counter.get();
              sz += cle.dataSize;
            }
            double time = (System.currentTimeMillis() - start) / 1000.0;
            double avg = (temp / time);
            System.out.println(
                String.format(
                    "second %d mem max %dmb allocated %dmb free %dmb mutations %d since start %d avg %.3f transfer %.3fmb",
                    ((System.currentTimeMillis() - start) / 1000),
                    maxMemory,
                    allocatedMemory,
                    freeMemory,
                    (temp - lastUpdate),
                    lastUpdate,
                    avg,
                    mb(sz / time)));
            lastUpdate = temp;
          }
        };
    ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
    scheduled.scheduleAtFixedRate(printRunnable, 1, 1, TimeUnit.SECONDS);
    return scheduled;
  }
  public void makeLog() throws IOException, InterruptedException {
    CommitLog commitLog = CommitLog.instance;
    System.out.format(
        "\nUsing commit log size %dmb, compressor %s, sync %s%s\n",
        mb(DatabaseDescriptor.getCommitLogSegmentSize()),
        commitLog.configuration.getCompressorName(),
        commitLog.executor.getClass().getSimpleName(),
        randomSize ? " random size" : "");
    final List<CommitlogExecutor> threads = new ArrayList<>();
    ScheduledExecutorService scheduled = startThreads(commitLog, threads);

    Thread.sleep(runTimeMs);
    stop = true;
    scheduled.shutdown();
    scheduled.awaitTermination(2, TimeUnit.SECONDS);

    int hash = 0;
    int cells = 0;
    for (CommitlogExecutor t : threads) {
      t.join();
      hash += t.hash;
      cells += t.cells;
    }
    commitLog.shutdownBlocking();

    File dataDir = new File(CommitLogUpgradeTest.DATA_DIR + FBUtilities.getReleaseVersionString());
    System.out.format("Data will be stored in %s\n", dataDir);
    if (dataDir.exists()) FileUtils.deleteRecursive(dataDir);

    dataDir.mkdirs();
    for (File f : new File(DatabaseDescriptor.getCommitLogLocation()).listFiles())
      FileUtils.createHardLink(f, new File(dataDir, f.getName()));

    Properties prop = new Properties();
    prop.setProperty(CFID_PROPERTY, Schema.instance.getId(KEYSPACE, TABLE).toString());
    prop.setProperty(CELLS_PROPERTY, Integer.toString(cells));
    prop.setProperty(HASH_PROPERTY, Integer.toString(hash));
    prop.store(
        new FileOutputStream(new File(dataDir, PROPERTIES_FILE)),
        "CommitLog upgrade test, version " + FBUtilities.getReleaseVersionString());
    System.out.println("Done");
  }