content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.cli;
  
  import alluxio.AlluxioURI;
  import alluxio.client.file.FileOutStream;
  import alluxio.client.file.FileSystem;
  import alluxio.conf.AlluxioConfiguration;
  import alluxio.conf.Configuration;
  import alluxio.exception.AlluxioException;
  import alluxio.grpc.CreateFilePOptions;
  import alluxio.util.io.PathUtils;
  
  import com.beust.jcommander.JCommander;
  import com.beust.jcommander.Parameter;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import java.util.UUID;
  import java.util.concurrent.atomic.AtomicInteger;
  
  /**
   * Class for running an operation multiple times.
   */
  public class RunOperation {
    private static final String BASE_DIRECTORY = "/RunOperationDir";
  
    enum Operation {
      CreateFile,
      CreateEmptyFile,
      CreateAndDeleteEmptyFile,
      ListStatus,
    }
  
    @Parameter(names = {"-op", "-operation"},
        description = "the operation to perform. Options are [CreateEmptyFile, "
            + "CreateAndDeleteEmptyFile, CreateFile, ListStatus]",
        required = true)
    private Operation mOperation;
    @Parameter(names = {"-n", "-num"},
        description = "the number of times to perform the operation (total for all threads)")
    private int mTimes = 1;
    @Parameter(names = {"-t", "-threads"}, description = "the number of threads to use")
    private int mThreads = 1;
    @Parameter(names = {"-d", "-dir"}, description = "The directory to perform operations in")
    private String mDir = BASE_DIRECTORY;
    @Parameter(names = {"-s", "-size"},
        description = "The size of a file to create")
    private int mSize = 4096;
  
    private byte[] mFiledata;
  
    private final FileSystem mFileSystem;
  
    /** Remaining number of times that the operation should be performed. */
    private AtomicInteger mRemainingOps;
  
    /**
     * Tool for running an operation multiple times.
     *
     * @param args command-line arguments
     */
    public static void main(String[] args) {
      System.exit(new RunOperation(Configuration.global()).run(args));
    }
  
    /**
     * Constructs a new {@link RunOperation} object.
     *
     * @param alluxioConf Alluxio configuration
     */
    public RunOperation(AlluxioConfiguration alluxioConf) {
      mFileSystem = FileSystem.Factory.create(alluxioConf);
    }
  
    /**
     * @param args command line arguments
     * @return the exit status
     */
    public int run(String[] args) {
      JCommander jc = new JCommander(this);
      jc.setProgramName("runOperation");
      try {
        jc.parse(args);
      } catch (Exception e) {
        System.out.println(e);
        System.out.println();
        jc.usage();
        return -1;
      }
      mRemainingOps = new AtomicInteger(mTimes);
      mFiledata = new byte[mSize];
      Arrays.fill(mFiledata, (byte) 0x7A);
  
      List<Thread> threads = new ArrayList<>();
      for (int i = 0; i < mThreads; i++) {
        threads.add(new OperationThread());
      }
      long start = System.currentTimeMillis();
      for (Thread thread : threads) {
        thread.start();
      }
      for (Thread thread : threads) {
        try {
          thread.join();
        } catch (InterruptedException e) {
          return -1;
        }
      }
      System.out.println("Completed in " + (System.currentTimeMillis() - start) + "ms");
      return 0;
    }
  
    private final class OperationThread extends Thread {
      private OperationThread() {}
  
      @Override
      public void run() {
        while (mRemainingOps.decrementAndGet() >= 0) {
          try {
            applyOperation();
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
        }
      }
  
      private void applyOperation() throws IOException, AlluxioException {
        AlluxioURI uri = new AlluxioURI(PathUtils.concatPath(mDir, UUID.randomUUID()));
        switch (mOperation) {
          case CreateEmptyFile:
            mFileSystem.createFile(uri).close();
            break;
          case CreateAndDeleteEmptyFile:
            mFileSystem.createFile(uri).close();
            mFileSystem.delete(uri);
            break;
          case CreateFile:
            try (FileOutStream file =
                mFileSystem.createFile(uri,
                    CreateFilePOptions.newBuilder().setRecursive(true).build())) {
              file.write(mFiledata);
            }
            break;
          case ListStatus:
            mFileSystem.listStatus(new AlluxioURI(mDir));
            break;
          default:
            throw new IllegalStateException("Unknown operation: " + mOperation);
        }
      }
    }
  }
  