public static void main(String[] args) {
    LlapStatusServiceCommandLine cl = LlapStatusServiceCommandLine.parseArguments(args);
    LlapStatusServiceDriver statusServiceDriver = createServiceDriver();

    ExitCode ret = ExitCode.SUCCESS;
    Clock clock = SystemClock.getInstance();
    long lastSummaryLogTime = -1;

    boolean firstAttempt = true;
    final long refreshInterval = cl.getRefreshIntervalMs();
    final boolean watchMode = cl.isWatchMode();
    final long watchTimeout = cl.getWatchTimeoutMs();
    long numAttempts = watchTimeout / refreshInterval;
    numAttempts = watchMode ? numAttempts : 1; // Break out of the loop fast if watchMode is disabled.
    State launchingState = null;
    State currentState = null;
    boolean desiredStateAttained = false;
    final float runningNodesThreshold = cl.getRunningNodesThreshold();
    try (OutputStream os = cl.getOutputFile() == null ? System.out : new FileOutputStream(cl.getOutputFile());
         Writer w = new OutputStreamWriter(os, Charset.defaultCharset());
         PrintWriter pw = new PrintWriter(w)) {

      LOG.info("Configured refresh interval: {}s. Watch timeout: {}s. Attempts remaining: {}." +
          " Watch mode: {}. Running nodes threshold: {}.", refreshInterval/1000, watchTimeout/1000,
          numAttempts, watchMode, new DecimalFormat("#.###").format(runningNodesThreshold));
      while (numAttempts > 0) {
        if (!firstAttempt) {
          if (watchMode) {
            try {
              Thread.sleep(refreshInterval);
            } catch (InterruptedException e) {
              // ignore
            }
          } else {
            // reported once, so break
            break;
          }
        } else {
          firstAttempt = false;
        }
        ret = statusServiceDriver.run(cl, watchMode ? watchTimeout : 0);
        currentState = statusServiceDriver.appStatusBuilder.getState();
        try {
          lastSummaryLogTime = LlapStatusServiceDriver.maybeLogSummary(clock, lastSummaryLogTime,
              statusServiceDriver, watchMode, watchTimeout, launchingState);
        } catch (Exception e) {
          LOG.warn("Failed to log summary", e);
        }

        if (ret == ExitCode.SUCCESS) {
          if (watchMode) {

            // YARN Service has started llap application, now if for some reason
            // state changes to COMPLETE then fail fast
            if (launchingState == null && LAUNCHING_STATES.contains(currentState)) {
              launchingState = currentState;
            }

            if (currentState.equals(State.COMPLETE)) {
              if (launchingState != null || cl.isLaunched()) {
                LOG.warn("COMPLETE state reached while waiting for RUNNING state. Failing.");
                System.err.println("Final diagnostics: " + statusServiceDriver.appStatusBuilder.getDiagnostics());
                break;
              } else {
                LOG.info("Found a stopped application; assuming it was a previous attempt "
                    + "and waiting for the next one. Omit the -l flag to avoid this.");
              }
            }

            if (!(currentState.equals(State.RUNNING_PARTIAL) || currentState.equals(State.RUNNING_ALL))) {
              LOG.debug(
                  "Current state: {}. Desired state: {}. {}/{} instances.",
                  currentState,
                  runningNodesThreshold == 1.0f ?
                      State.RUNNING_ALL :
                      State.RUNNING_PARTIAL,
                  statusServiceDriver.appStatusBuilder.getLiveInstances(),
                  statusServiceDriver.appStatusBuilder.getDesiredInstances());
              numAttempts--;
              continue;
            }

            // we have reached RUNNING state, now check if running nodes threshold is met
            final int liveInstances = statusServiceDriver.appStatusBuilder.getLiveInstances();
            final int desiredInstances = statusServiceDriver.appStatusBuilder.getDesiredInstances();
            if (desiredInstances > 0) {
              final float ratio = (float) liveInstances / (float) desiredInstances;
              if (ratio < runningNodesThreshold) {
                LOG.debug(
                    "Waiting until running nodes threshold is reached. Current: {} Desired: {}." +
                        " {}/{} instances.",
                    new DecimalFormat("#.###").format(ratio),
                    new DecimalFormat("#.###").format(runningNodesThreshold),
                    statusServiceDriver.appStatusBuilder.getLiveInstances(),
                    statusServiceDriver.appStatusBuilder.getDesiredInstances());
                numAttempts--;
                continue;
              } else {
                desiredStateAttained = true;
                statusServiceDriver.appStatusBuilder.setRunningThresholdAchieved(true);
              }
            } else {
              numAttempts--;
              continue;
            }
          }
        } else if (ret == ExitCode.YARN_ERROR && watchMode) {
          LOG.warn("Watch mode enabled and got YARN error. Retrying..");
          numAttempts--;
          continue;
        } else if (ret == ExitCode.SERVICE_CLIENT_ERROR_CREATE_FAILED && watchMode) {
          LOG.warn("Watch mode enabled and YARN Service client creation failed. Retrying..");
          numAttempts--;
          continue;
        } else if (ret == ExitCode.SERVICE_CLIENT_ERROR_OTHER && watchMode) {
          LOG.warn("Watch mode enabled and got YARN Service client error. Retrying..");
          numAttempts--;
          continue;
        } else if (ret == ExitCode.LLAP_REGISTRY_ERROR && watchMode) {
          LOG.warn("Watch mode enabled and got LLAP registry error. Retrying..");
          numAttempts--;
          continue;
        }
        break;
      }
      // Log final state to CONSOLE_LOGGER
      maybeLogSummary(clock, 0L, statusServiceDriver, watchMode, watchTimeout, launchingState);
      CONSOLE_LOGGER.info("\n\n\n");

      statusServiceDriver.outputJson(pw); // print current state before exiting
      pw.flush();
      if (numAttempts == 0 && watchMode && !desiredStateAttained) {
        LOG.warn("Watch timeout {}s exhausted before desired state RUNNING is attained.", watchTimeout/1000);
      }
    } catch (Throwable t) {
      logError(t);
      if (t instanceof LlapStatusCliException) {
        LlapStatusCliException ce = (LlapStatusCliException) t;
        ret = ce.getExitCode();
      } else {
        ret = ExitCode.INTERNAL_ERROR;
      }
    } finally {
      LOG.info("LLAP status finished");
      if (ret != ExitCode.SUCCESS) {
        LOG.error("LLAP did not start. Check the application log for more info:\n" +
            "\tyarn logs --applicationId {} -out <path>", statusServiceDriver.applicationId);
      }
      statusServiceDriver.close();
    }
    LOG.debug("Completed processing - exiting with " + ret);

    // HACK: due to the System.exit some log messages may not be present.
    try {
      Thread.sleep(1000);
    } catch (Exception e) {
      // ignore
    }
    System.exit(ret.getCode());
  }
Populate additional information for containers from the LLAP registry. Must be invoked
after YARN Service status and diagnostics.
@return an ExitCode. An ExitCode other than ExitCode.SUCCESS implies future progress not possible
@throws LlapStatusCliException
llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceDriver.java