public void exec(int depth, int concurrencyDepth, AlluxioURI path) throws Exception {
   if (depth < 1) {
     return;
   } else if (depth == 1 || (path.hashCode() % 10 == 0)) {
     // Sometimes we want to try deleting a path when we're not all the way down, which is what
     // the second condition is for.
     doDelete(path);
   } else {
     if (concurrencyDepth > 0) {
       ExecutorService executor = Executors.newCachedThreadPool();
       try {
         ArrayList<Future<Void>> futures = new ArrayList<Future<Void>>(FILES_PER_NODE);
         for (int i = 0; i < FILES_PER_NODE; i++) {
           Callable<Void> call =
               (new ConcurrentDeleter(
                   depth - 1, concurrencyDepth - 1, path.join(Integer.toString(i))));
           futures.add(executor.submit(call));
         }
         for (Future<Void> f : futures) {
           f.get();
         }
       } finally {
         executor.shutdown();
       }
     } else {
       for (int i = 0; i < FILES_PER_NODE; i++) {
         exec(depth - 1, concurrencyDepth, path.join(Integer.toString(i)));
       }
     }
     doDelete(path);
   }
 }
 public void exec(int depth, int concurrencyDepth, AlluxioURI path) throws Exception {
   if (depth < 1) {
     return;
   } else if (depth == 1 || (depth < mDepth && path.hashCode() % 10 < 3)) {
     // Sometimes we want to try renaming a path when we're not all the way down, which is what
     // the second condition is for. We have to create the path in the destination up till what
     // we're renaming. This might already exist, so createFile could throw a
     // FileAlreadyExistsException, which we silently handle.
     AlluxioURI srcPath = mRootPath.join(path);
     AlluxioURI dstPath = mRootPath2.join(path);
     long fileId = mFsMaster.getFileId(srcPath);
     try {
       CreateDirectoryOptions options = CreateDirectoryOptions.defaults().setRecursive(true);
       mFsMaster.createDirectory(dstPath.getParent(), options);
     } catch (FileAlreadyExistsException e) {
       // This is an acceptable exception to get, since we don't know if the parent has been
       // created yet by another thread.
     } catch (InvalidPathException e) {
       // This could happen if we are renaming something that's a child of the root.
     }
     mFsMaster.rename(srcPath, dstPath);
     Assert.assertEquals(fileId, mFsMaster.getFileId(dstPath));
   } else if (concurrencyDepth > 0) {
     ExecutorService executor = Executors.newCachedThreadPool();
     try {
       ArrayList<Future<Void>> futures = new ArrayList<Future<Void>>(FILES_PER_NODE);
       for (int i = 0; i < FILES_PER_NODE; i++) {
         Callable<Void> call =
             (new ConcurrentRenamer(
                 depth - 1,
                 concurrencyDepth - 1,
                 mRootPath,
                 mRootPath2,
                 path.join(Integer.toString(i))));
         futures.add(executor.submit(call));
       }
       for (Future<Void> f : futures) {
         f.get();
       }
     } finally {
       executor.shutdown();
     }
   } else {
     for (int i = 0; i < FILES_PER_NODE; i++) {
       exec(depth - 1, concurrencyDepth, path.join(Integer.toString(i)));
     }
   }
 }