HIVE-20807 : Refactor LlapStatusServiceDriver (Miklos Gergely via Sergey Shelukhin)
Signed-off-by: Ashutosh Chauhan <hashut...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/af401702 Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/af401702 Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/af401702 Branch: refs/heads/master Commit: af401702847391ab41fcf2ef8216a94a1b7bfc76 Parents: bc39c49 Author: Miklos Gergely <mgerg...@hortonworks.com> Authored: Thu Oct 25 13:03:00 2018 -0700 Committer: Ashutosh Chauhan <hashut...@apache.org> Committed: Mon Nov 12 15:28:18 2018 -0800 ---------------------------------------------------------------------- bin/ext/llapstatus.sh | 4 +- .../hadoop/hive/llap/cli/LlapSliderUtils.java | 55 +- .../llap/cli/LlapStatusOptionsProcessor.java | 278 ------- .../hive/llap/cli/LlapStatusServiceDriver.java | 811 ------------------- .../hadoop/hive/llap/cli/status/AmInfo.java | 93 +++ .../hive/llap/cli/status/AppStatusBuilder.java | 231 ++++++ .../hadoop/hive/llap/cli/status/ExitCode.java | 44 + .../hive/llap/cli/status/LlapInstance.java | 134 +++ .../llap/cli/status/LlapStatusCliException.java | 40 + .../hive/llap/cli/status/LlapStatusHelpers.java | 449 ---------- .../status/LlapStatusServiceCommandLine.java | 302 +++++++ .../cli/status/LlapStatusServiceDriver.java | 775 ++++++++++++++++++ .../hadoop/hive/llap/cli/status/State.java | 31 + .../hive/llap/cli/status/package-info.java | 24 + .../llap/cli/TestLlapStatusServiceDriver.java | 98 --- .../TestLlapStatusServiceCommandLine.java | 91 +++ .../hive/llap/cli/status/package-info.java | 23 + .../java/org/apache/hive/http/LlapServlet.java | 9 +- 18 files changed, 1799 insertions(+), 1693 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/bin/ext/llapstatus.sh ---------------------------------------------------------------------- diff --git a/bin/ext/llapstatus.sh b/bin/ext/llapstatus.sh index 2d2c8f4..23e6be6 100644 --- a/bin/ext/llapstatus.sh +++ b/bin/ext/llapstatus.sh @@ -17,7 +17,7 @@ THISSERVICE=llapstatus export SERVICE_LIST="${SERVICE_LIST}${THISSERVICE} " llapstatus () { - CLASS=org.apache.hadoop.hive.llap.cli.LlapStatusServiceDriver; + CLASS=org.apache.hadoop.hive.llap.cli.status.LlapStatusServiceDriver; if [ ! -f ${HIVE_LIB}/hive-cli-*.jar ]; then echo "Missing Hive CLI Jar" exit 3; @@ -36,7 +36,7 @@ llapstatus () { } llapstatus_help () { - CLASS=org.apache.hadoop.hive.llap.cli.LlapStatusServiceDriver; + CLASS=org.apache.hadoop.hive.llap.cli.status.LlapStatusServiceDriver; execHiveCmd $CLASS "--help" } http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapSliderUtils.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapSliderUtils.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapSliderUtils.java index af47b26..5ec9e1d 100644 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapSliderUtils.java +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapSliderUtils.java @@ -24,69 +24,24 @@ import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.Path; -import org.apache.hadoop.yarn.api.records.ApplicationId; -import org.apache.hadoop.yarn.api.records.ApplicationReport; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.client.ServiceClient; import org.apache.hadoop.yarn.service.utils.CoreFileSystem; -import org.apache.hadoop.yarn.util.Clock; -import org.apache.hadoop.yarn.util.SystemClock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LlapSliderUtils { - private static final Logger LOG = LoggerFactory - .getLogger(LlapSliderUtils.class); + private static final Logger LOG = LoggerFactory.getLogger(LlapSliderUtils.class); private static final String LLAP_PACKAGE_DIR = ".yarn/package/LLAP/"; - public static ServiceClient createServiceClient( - Configuration conf) throws Exception { + public static ServiceClient createServiceClient(Configuration conf) throws Exception { ServiceClient serviceClient = new ServiceClient(); serviceClient.init(conf); serviceClient.start(); return serviceClient; } - public static ApplicationReport getAppReport(String appName, ServiceClient serviceClient, - long timeoutMs) throws - LlapStatusServiceDriver.LlapStatusCliException { - Clock clock = SystemClock.getInstance(); - long startTime = clock.getTime(); - long timeoutTime = timeoutMs < 0 ? Long.MAX_VALUE : (startTime + timeoutMs); - ApplicationReport appReport = null; - ApplicationId appId; - try { - appId = serviceClient.getAppId(appName); - } catch (YarnException | IOException e) { - return null; - } - - while (appReport == null) { - try { - appReport = serviceClient.getYarnClient().getApplicationReport(appId); - if (timeoutMs == 0) { - // break immediately if timeout is 0 - break; - } - // Otherwise sleep, and try again. - if (appReport == null) { - long remainingTime = Math.min(timeoutTime - clock.getTime(), 500l); - if (remainingTime > 0) { - Thread.sleep(remainingTime); - } else { - break; - } - } - } catch (Exception e) { // No point separating IOException vs YarnException vs others - throw new LlapStatusServiceDriver.LlapStatusCliException( - LlapStatusServiceDriver.ExitCode.YARN_ERROR, - "Failed to get Yarn AppReport", e); - } - } - return appReport; - } - public static Service getService(Configuration conf, String name) { LOG.info("Get service details for " + name); ServiceClient sc; @@ -112,10 +67,8 @@ public class LlapSliderUtils { return service; } - public static void startCluster(Configuration conf, String name, - String packageName, Path packageDir, String queue) { - LOG.info("Starting cluster with " + name + ", " - + packageName + ", " + queue + ", " + packageDir); + public static void startCluster(Configuration conf, String name, String packageName, Path packageDir, String queue) { + LOG.info("Starting cluster with " + name + ", " + packageName + ", " + queue + ", " + packageDir); ServiceClient sc; try { sc = createServiceClient(conf); http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusOptionsProcessor.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusOptionsProcessor.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusOptionsProcessor.java deleted file mode 100644 index dca0c7b..0000000 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusOptionsProcessor.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hive.llap.cli; - -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -import jline.TerminalFactory; -import org.apache.commons.cli.GnuParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.OptionBuilder; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; - -import com.google.common.annotations.VisibleForTesting; - -public class LlapStatusOptionsProcessor { - - private static final String LLAPSTATUS_CONSTANT = "llapstatus"; - - @VisibleForTesting - public static final long FIND_YARN_APP_TIMEOUT_MS = 20 * 1000l; // 20seconds to wait for app to be visible - @VisibleForTesting - public static final long DEFAULT_STATUS_REFRESH_INTERVAL_MS = 1 * 1000l; // 1 seconds wait until subsequent status - @VisibleForTesting - public static final long DEFAULT_WATCH_MODE_TIMEOUT_MS = 5 * 60 * 1000l; // 5 minutes timeout for watch mode - @VisibleForTesting - public static final float DEFAULT_RUNNING_NODES_THRESHOLD = 1.0f; - - // TODO: why doesn't this use one of the existing options implementations?! - enum OptionConstants { - - NAME("name", 'n', "LLAP cluster name", true), - FIND_APP_TIMEOUT("findAppTimeout", 'f', - "Amount of time(s) that the tool will sleep to wait for the YARN application to start. negative values=wait " + - "forever, 0=Do not wait. default=" + TimeUnit.SECONDS.convert(FIND_YARN_APP_TIMEOUT_MS, TimeUnit.MILLISECONDS) + - "s", true), - OUTPUT_FILE("outputFile", 'o', "File to which output should be written (Default stdout)", true), - WATCH_MODE("watch", 'w', "Watch mode waits until all LLAP daemons are running or subset of the nodes are " + - "running (threshold can be specified via -r option) (Default wait until all nodes are running)", false), - // This is a negative because we want the positive to be the default when nothing is specified. - NOT_LAUNCHED("notlaunched", 'l', "In watch mode, do not assume that the application was " - + "already launched if there's doubt (e.g. if the last application instance has failed).", - false), - RUNNING_NODES_THRESHOLD("runningNodesThreshold", 'r', "When watch mode is enabled (-w), wait until the " + - "specified threshold of nodes are running (Default 1.0 which means 100% nodes are running)", true), - STATUS_REFRESH_INTERVAL("refreshInterval", 'i', "Amount of time in seconds to wait until subsequent status checks" + - " in watch mode. Valid only for watch mode. (Default " + - TimeUnit.SECONDS.convert(DEFAULT_STATUS_REFRESH_INTERVAL_MS, TimeUnit.MILLISECONDS) + "s)", true), - WATCH_MODE_TIMEOUT("watchTimeout", 't', "Exit watch mode if the desired state is not attained until the specified" + - " timeout. (Default " + TimeUnit.SECONDS.convert(DEFAULT_WATCH_MODE_TIMEOUT_MS, TimeUnit.MILLISECONDS) +"s)", - true), - HIVECONF("hiveconf", null, "Use value for given property. Overridden by explicit parameters", "property=value", 2), - HELP("help", 'H', "Print help information", false); - - - private final String longOpt; - private final Character shortOpt; - private final String description; - private final String argName; - private final int numArgs; - - OptionConstants(String longOpt, char shortOpt, String description, boolean hasArgs) { - this(longOpt, shortOpt, description, longOpt, hasArgs ? 1 : 0); - } - - OptionConstants(String longOpt, Character shortOpt, String description, String argName, int numArgs) { - this.longOpt = longOpt; - this.shortOpt = shortOpt; - this.description = description; - this.argName = argName; - this.numArgs = numArgs; - } - - public String getLongOpt() { - return longOpt; - } - - public Character getShortOpt() { - return shortOpt; - } - - public String getDescription() { - return description; - } - - public String getArgName() { - return argName; - } - - public int getNumArgs() { - return numArgs; - } - } - - - public static class LlapStatusOptions { - private final String name; - private final Properties conf; - private final long findAppTimeoutMs; - private final String outputFile; - private final long refreshIntervalMs; - private final boolean watchMode; - private final long watchTimeout; - private final float runningNodesThreshold; - private final boolean isLaunched; - - public LlapStatusOptions(final String name) { - this(name, new Properties(), FIND_YARN_APP_TIMEOUT_MS, null, DEFAULT_STATUS_REFRESH_INTERVAL_MS, false, - DEFAULT_WATCH_MODE_TIMEOUT_MS, DEFAULT_RUNNING_NODES_THRESHOLD, true); - } - - public LlapStatusOptions(String name, Properties hiveProperties, long findAppTimeoutMs, - String outputFile, long refreshIntervalMs, - final boolean watchMode, final long watchTimeoutMs, - final float runningNodesThreshold, final boolean isLaunched) { - this.name = name; - this.conf = hiveProperties; - this.findAppTimeoutMs = findAppTimeoutMs; - this.outputFile = outputFile; - this.refreshIntervalMs = refreshIntervalMs; - this.watchMode = watchMode; - this.watchTimeout = watchTimeoutMs; - this.runningNodesThreshold = runningNodesThreshold; - this.isLaunched = isLaunched; - } - - public String getName() { - return name; - } - - public Properties getConf() { - return conf; - } - - public long getFindAppTimeoutMs() { - return findAppTimeoutMs; - } - - public String getOutputFile() { - return outputFile; - } - - public long getRefreshIntervalMs() { - return refreshIntervalMs; - } - - public boolean isWatchMode() { - return watchMode; - } - - public boolean isLaunched() { - return isLaunched; - } - - public long getWatchTimeoutMs() { - return watchTimeout; - } - - public float getRunningNodesThreshold() { - return runningNodesThreshold; - } - } - - private final Options options = new Options(); - private org.apache.commons.cli.CommandLine commandLine; - - public LlapStatusOptionsProcessor() { - - for (OptionConstants optionConstant : OptionConstants.values()) { - - OptionBuilder optionBuilder = OptionBuilder.hasArgs(optionConstant.getNumArgs()) - .withArgName(optionConstant.getArgName()).withLongOpt(optionConstant.getLongOpt()) - .withDescription(optionConstant.getDescription()); - if (optionConstant.getShortOpt() == null) { - options.addOption(optionBuilder.create()); - } else { - options.addOption(optionBuilder.create(optionConstant.getShortOpt())); - } - } - } - - public LlapStatusOptions processOptions(String[] args) throws ParseException { - commandLine = new GnuParser().parse(options, args); - if (commandLine.hasOption(OptionConstants.HELP.getShortOpt())) { - printUsage(); - return null; - } - - String name = commandLine.getOptionValue(OptionConstants.NAME.getLongOpt()); - - long findAppTimeoutMs = FIND_YARN_APP_TIMEOUT_MS; - if (commandLine.hasOption(OptionConstants.FIND_APP_TIMEOUT.getLongOpt())) { - findAppTimeoutMs = TimeUnit.MILLISECONDS.convert(Long.parseLong( - commandLine.getOptionValue(OptionConstants.FIND_APP_TIMEOUT.getLongOpt())), - TimeUnit.SECONDS); - } - - Properties hiveConf; - if (commandLine.hasOption(OptionConstants.HIVECONF.getLongOpt())) { - hiveConf = commandLine.getOptionProperties(OptionConstants.HIVECONF.getLongOpt()); - } else { - hiveConf = new Properties(); - } - - String outputFile = null; - if (commandLine.hasOption(OptionConstants.OUTPUT_FILE.getLongOpt())) { - outputFile = commandLine.getOptionValue(OptionConstants.OUTPUT_FILE.getLongOpt()); - } - - long refreshIntervalMs = DEFAULT_STATUS_REFRESH_INTERVAL_MS; - if (commandLine.hasOption(OptionConstants.STATUS_REFRESH_INTERVAL.getLongOpt())) { - long refreshIntervalSec = Long.parseLong(commandLine.getOptionValue(OptionConstants.STATUS_REFRESH_INTERVAL - .getLongOpt())); - if (refreshIntervalSec <= 0) { - throw new IllegalArgumentException("Refresh interval should be >0"); - } - refreshIntervalMs = TimeUnit.MILLISECONDS.convert(refreshIntervalSec, TimeUnit.SECONDS); - } - - boolean watchMode = commandLine.hasOption(OptionConstants.WATCH_MODE.getLongOpt()); - long watchTimeoutMs = DEFAULT_WATCH_MODE_TIMEOUT_MS; - if (commandLine.hasOption(OptionConstants.WATCH_MODE_TIMEOUT.getLongOpt())) { - long watchTimeoutSec = Long.parseLong(commandLine.getOptionValue( - OptionConstants.WATCH_MODE_TIMEOUT.getLongOpt())); - if (watchTimeoutSec <= 0) { - throw new IllegalArgumentException("Watch timeout should be >0"); - } - watchTimeoutMs = TimeUnit.MILLISECONDS.convert(watchTimeoutSec, TimeUnit.SECONDS); - } - - boolean isLaunched = !commandLine.hasOption(OptionConstants.NOT_LAUNCHED.getLongOpt()); - - float runningNodesThreshold = DEFAULT_RUNNING_NODES_THRESHOLD; - if (commandLine.hasOption(OptionConstants.RUNNING_NODES_THRESHOLD.getLongOpt())) { - runningNodesThreshold = Float.parseFloat(commandLine.getOptionValue( - OptionConstants.RUNNING_NODES_THRESHOLD.getLongOpt())); - if (runningNodesThreshold < 0.0f || runningNodesThreshold > 1.0f) { - throw new IllegalArgumentException( - "Running nodes threshold value should be between 0.0 and 1.0 (inclusive)"); - } - } - return new LlapStatusOptions(name, hiveConf, findAppTimeoutMs, outputFile, refreshIntervalMs, - watchMode, watchTimeoutMs, runningNodesThreshold, isLaunched); - } - - - public static void printUsage() { - HelpFormatter hf = new HelpFormatter(); - try { - int width = hf.getWidth(); - int jlineWidth = TerminalFactory.get().getWidth(); - width = Math.min(160, Math.max(jlineWidth, width)); // Ignore potentially incorrect values - hf.setWidth(width); - } catch (Throwable t) { // Ignore - } - - LlapStatusOptionsProcessor optionsProcessor = new LlapStatusOptionsProcessor(); - hf.printHelp(LLAPSTATUS_CONSTANT, optionsProcessor.options); - } - -} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusServiceDriver.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusServiceDriver.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusServiceDriver.java deleted file mode 100644 index a521799..0000000 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/LlapStatusServiceDriver.java +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hive.llap.cli; - - -import com.google.common.annotations.VisibleForTesting; -import java.io.BufferedOutputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CommonConfigurationKeysPublic; -import org.apache.hadoop.hive.common.classification.InterfaceAudience; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.llap.cli.LlapStatusOptionsProcessor.LlapStatusOptions; -import org.apache.hadoop.hive.llap.cli.status.LlapStatusHelpers; -import org.apache.hadoop.hive.llap.cli.status.LlapStatusHelpers.AppStatusBuilder; -import org.apache.hadoop.hive.llap.cli.status.LlapStatusHelpers.LlapInstance; -import org.apache.hadoop.hive.llap.cli.status.LlapStatusHelpers.State; -import org.apache.hadoop.hive.llap.configuration.LlapDaemonConfiguration; -import org.apache.hadoop.hive.llap.registry.LlapServiceInstance; -import org.apache.hadoop.hive.llap.registry.impl.LlapRegistryService; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.apache.hadoop.yarn.api.records.ApplicationReport; -import org.apache.hadoop.yarn.api.records.ContainerExitStatus; -import org.apache.hadoop.yarn.conf.YarnConfiguration; -import org.apache.hadoop.yarn.exceptions.YarnException; -import org.apache.hadoop.yarn.service.api.records.Container; -import org.apache.hadoop.yarn.service.api.records.Service; -import org.apache.hadoop.yarn.service.api.records.ServiceState; -import org.apache.hadoop.yarn.service.client.ServiceClient; -import org.apache.hadoop.yarn.util.Clock; -import org.apache.hadoop.yarn.util.SystemClock; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.SerializationConfig; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LlapStatusServiceDriver { - private static final Logger LOG = LoggerFactory.getLogger(LlapStatusServiceDriver.class); - private static final Logger CONSOLE_LOGGER = LoggerFactory.getLogger("LlapStatusServiceDriverConsole"); - - private static final EnumSet<State> NO_YARN_SERVICE_INFO_STATES = EnumSet.of( - State.APP_NOT_FOUND, State.COMPLETE, State.LAUNCHING); - private static final EnumSet<State> LAUNCHING_STATES = EnumSet.of( - State.LAUNCHING, State.RUNNING_PARTIAL, State.RUNNING_ALL); - - // Defining a bunch of configs here instead of in HiveConf. These are experimental, and mainly - // for use when retry handling is fixed in Yarn/Hadoop - - private static final String CONF_PREFIX = "hive.llapcli."; - - // The following two keys should ideally be used to control RM connect timeouts. However, - // they don't seem to work. The IPC timeout needs to be set instead. - @InterfaceAudience.Private - private static final String CONFIG_YARN_RM_TIMEOUT_MAX_WAIT_MS = CONF_PREFIX + "yarn.rm.connect.max-wait-ms"; - private static final long CONFIG_YARN_RM_TIMEOUT_MAX_WAIT_MS_DEFAULT = 10000l; - @InterfaceAudience.Private - private static final String CONFIG_YARN_RM_RETRY_INTERVAL_MS = CONF_PREFIX + "yarn.rm.connect.retry-interval.ms"; - private static final long CONFIG_YARN_RM_RETRY_INTERVAL_MS_DEFAULT = 5000l; - - // As of Hadoop 2.7 - this is what controls the RM timeout. - @InterfaceAudience.Private - private static final String CONFIG_IPC_CLIENT_CONNECT_MAX_RETRIES = CONF_PREFIX + "ipc.client.max-retries"; - private static final int CONFIG_IPC_CLIENT_CONNECT_MAX_RETRIES_DEFAULT = 2; - @InterfaceAudience.Private - private static final String CONFIG_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS = - CONF_PREFIX + "ipc.client.connect.retry-interval-ms"; - private static final long CONFIG_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS_DEFAULT = 1500l; - - // As of Hadoop 2.8 - this timeout spec behaves in a strnage manner. "2000,1" means 2000s with 1 retry. - // However it does this - but does it thrice. Essentially - #retries+2 is the number of times the entire config - // is retried. "2000,1" means 3 retries - each with 1 retry with a random 2000ms sleep. - @InterfaceAudience.Private - private static final String CONFIG_TIMELINE_SERVICE_ENTITYGROUP_FS_STORE_RETRY_POLICY_SPEC = - CONF_PREFIX + "timeline.service.fs-store.retry.policy.spec"; - private static final String - CONFIG_TIMELINE_SERVICE_ENTITYGROUP_FS_STORE_RETRY_POLICY_SPEC_DEFAULT = "2000, 1"; - - private static final String CONFIG_LLAP_ZK_REGISTRY_TIMEOUT_MS = CONF_PREFIX + "zk-registry.timeout-ms"; - private static final long CONFIG_LLAP_ZK_REGISTRY_TIMEOUT_MS_DEFAULT = 20000l; - - private static final long LOG_SUMMARY_INTERVAL = 15000L; // Log summary every ~15 seconds. - private static final String LLAP_KEY = "llap"; - - private final Configuration conf; - private String appName = null; - private String applicationId = null; - private ServiceClient serviceClient = null; - private Configuration llapRegistryConf = null; - private LlapRegistryService llapRegistry = null; - - private AppStatusBuilder appStatusBuilder; - - public LlapStatusServiceDriver() { - SessionState ss = SessionState.get(); - conf = (ss != null) ? ss.getConf() : new HiveConf(SessionState.class); - setupConf(); - } - - private void setupConf() { - for (String f : LlapDaemonConfiguration.DAEMON_CONFIGS) { - conf.addResource(f); - } - conf.reloadConfiguration(); - - // Setup timeouts for various services. - - // Once we move to a Hadoop-2.8 dependency, the following paramteer can be used. - // conf.set(YarnConfiguration.TIMELINE_SERVICE_ENTITYGROUP_FS_STORE_RETRY_POLICY_SPEC); - conf.set("yarn.timeline-service.entity-group-fs-store.retry-policy-spec", - conf.get(CONFIG_TIMELINE_SERVICE_ENTITYGROUP_FS_STORE_RETRY_POLICY_SPEC, - CONFIG_TIMELINE_SERVICE_ENTITYGROUP_FS_STORE_RETRY_POLICY_SPEC_DEFAULT)); - - conf.setLong(YarnConfiguration.RESOURCEMANAGER_CONNECT_MAX_WAIT_MS, - conf.getLong(CONFIG_YARN_RM_TIMEOUT_MAX_WAIT_MS, CONFIG_YARN_RM_TIMEOUT_MAX_WAIT_MS_DEFAULT)); - conf.setLong(YarnConfiguration.RESOURCEMANAGER_CONNECT_RETRY_INTERVAL_MS, - conf.getLong(CONFIG_YARN_RM_RETRY_INTERVAL_MS, CONFIG_YARN_RM_RETRY_INTERVAL_MS_DEFAULT)); - - conf.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, - conf.getInt(CONFIG_IPC_CLIENT_CONNECT_MAX_RETRIES, CONFIG_IPC_CLIENT_CONNECT_MAX_RETRIES_DEFAULT)); - conf.setLong(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_RETRY_INTERVAL_KEY, - conf.getLong(CONFIG_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS, CONFIG_IPC_CLIENT_CONNECT_RETRY_INTERVAL_MS_DEFAULT)); - - HiveConf.setVar(conf, HiveConf.ConfVars.HIVE_ZOOKEEPER_SESSION_TIMEOUT, ( - conf.getLong(CONFIG_LLAP_ZK_REGISTRY_TIMEOUT_MS, CONFIG_LLAP_ZK_REGISTRY_TIMEOUT_MS_DEFAULT) + "ms")); - - llapRegistryConf = new Configuration(conf); - } - - /** - * Parse command line options. - * - * @return command line options. - */ - @VisibleForTesting - public LlapStatusOptions parseOptions(String[] args) throws LlapStatusCliException { - - LlapStatusOptionsProcessor optionsProcessor = new LlapStatusOptionsProcessor(); - LlapStatusOptions options; - try { - options = optionsProcessor.processOptions(args); - return options; - } catch (Exception e) { - LOG.info("Failed to parse arguments", e); - throw new LlapStatusCliException(ExitCode.INCORRECT_USAGE, "Incorrect usage"); - } - } - - public int run(LlapStatusOptions options, long watchTimeoutMs) { - appStatusBuilder = new AppStatusBuilder(); - try { - if (appName == null) { - // user provided configs - for (Map.Entry<Object, Object> props : options.getConf().entrySet()) { - conf.set((String) props.getKey(), (String) props.getValue()); - } - - appName = options.getName(); - if (StringUtils.isEmpty(appName)) { - appName = HiveConf.getVar(conf, HiveConf.ConfVars.LLAP_DAEMON_SERVICE_HOSTS); - if (appName.startsWith("@") && appName.length() > 1) { - // This is a valid YARN Service name. Parse it out. - appName = appName.substring(1); - } else { - // Invalid app name. Checked later. - appName = null; - } - } - if (StringUtils.isEmpty(appName)) { - String message = - "Invalid app name. This must be setup via config or passed in as a parameter." + - " This tool works with clusters deployed by YARN Service"; - LOG.info(message); - return ExitCode.INCORRECT_USAGE.getInt(); - } - LOG.debug("Using appName: {}", appName); - - llapRegistryConf.set(HiveConf.ConfVars.LLAP_DAEMON_SERVICE_HOSTS.varname, "@" + appName); - } - - try { - if (serviceClient == null) { - serviceClient = LlapSliderUtils.createServiceClient(conf); - } - } catch (Exception e) { - LlapStatusCliException le = new LlapStatusCliException( - LlapStatusServiceDriver.ExitCode.SERVICE_CLIENT_ERROR_CREATE_FAILED, "Failed to create service client", e); - logError(le); - return le.getExitCode().getInt(); - } - - // Get the App report from YARN - ApplicationReport appReport; - try { - appReport = LlapSliderUtils.getAppReport(appName, serviceClient, options.getFindAppTimeoutMs()); - } catch (LlapStatusCliException e) { - logError(e); - return e.getExitCode().getInt(); - } - - // Process the report - ExitCode ret; - try { - ret = processAppReport(appReport, appStatusBuilder); - } catch (LlapStatusCliException e) { - logError(e); - return e.getExitCode().getInt(); - } - - if (ret != ExitCode.SUCCESS) { - return ret.getInt(); - } else if (NO_YARN_SERVICE_INFO_STATES.contains(appStatusBuilder.getState())) { - return ExitCode.SUCCESS.getInt(); - } else { - // Get information from YARN Service - try { - ret = populateAppStatusFromServiceStatus(appName, serviceClient, appStatusBuilder); - } catch (LlapStatusCliException e) { - // In case of failure, send back whatever is constructed so far - which would be from the AppReport - logError(e); - return e.getExitCode().getInt(); - } - } - - if (ret != ExitCode.SUCCESS) { - return ret.getInt(); - } else { - try { - ret = populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs); - } catch (LlapStatusCliException e) { - logError(e); - return e.getExitCode().getInt(); - } - } - - return ret.getInt(); - } finally { - LOG.debug("Final AppState: " + appStatusBuilder.toString()); - } - } - - public void outputJson(PrintWriter writer) throws LlapStatusCliException { - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); - mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); - mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY); - try { - writer.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(appStatusBuilder)); - } catch (IOException e) { - LOG.warn("Failed to create JSON", e); - throw new LlapStatusCliException(ExitCode.LLAP_JSON_GENERATION_ERROR, "Failed to create JSON", e); - } - } - - /** - * Populates parts of the AppStatus - * - * @return an ExitCode. An ExitCode other than ExitCode.SUCCESS implies future progress not possible - * @throws LlapStatusCliException - */ - private ExitCode processAppReport(ApplicationReport appReport, AppStatusBuilder appStatusBuilder) - throws LlapStatusCliException { - if (appReport == null) { - appStatusBuilder.setState(State.APP_NOT_FOUND); - LOG.info("No Application Found"); - return ExitCode.SUCCESS; - } - - applicationId = appReport.getApplicationId().toString(); - - // TODO Maybe add the YARN URL for the app. - appStatusBuilder.setAmInfo( - new LlapStatusHelpers.AmInfo().setAppName(appReport.getName()).setAppType(appReport.getApplicationType())); - appStatusBuilder.setAppStartTime(appReport.getStartTime()); - switch (appReport.getYarnApplicationState()) { - case NEW: - case NEW_SAVING: - case SUBMITTED: - appStatusBuilder.setState(State.LAUNCHING); - return ExitCode.SUCCESS; - case ACCEPTED: - appStatusBuilder.maybeCreateAndGetAmInfo().setAppId(applicationId); - appStatusBuilder.setState(State.LAUNCHING); - return ExitCode.SUCCESS; - case RUNNING: - appStatusBuilder.maybeCreateAndGetAmInfo().setAppId(applicationId); - // If the app state is running, get additional information from YARN Service - return ExitCode.SUCCESS; - case FINISHED: - case FAILED: - case KILLED: - appStatusBuilder.maybeCreateAndGetAmInfo().setAppId(applicationId); - appStatusBuilder.setAppFinishTime(appReport.getFinishTime()); - appStatusBuilder.setState(State.COMPLETE); - // add log links and other diagnostics from YARN Service - return ExitCode.SUCCESS; - default: - throw new LlapStatusCliException(ExitCode.INTERNAL_ERROR, - "Unknown Yarn Application State: " + appReport.getYarnApplicationState()); - } - } - - /** - * Populates information from YARN Service Status. - * - * @return an ExitCode. An ExitCode other than ExitCode.SUCCESS implies future progress not possible - * @throws LlapStatusCliException - */ - private ExitCode populateAppStatusFromServiceStatus(String appName, ServiceClient serviceClient, - AppStatusBuilder appStatusBuilder) throws LlapStatusCliException { - ExitCode exitCode = ExitCode.YARN_ERROR; - try { - Service service = serviceClient.getStatus(appName); - if (service != null) { - // How to get config paths and AmInfo - ServiceState state = service.getState(); - appStatusBuilder.setAppStartTime(service.getLaunchTime() == null ? 0 : service.getLaunchTime().getTime()); - appStatusBuilder.setDesiredInstances(service.getComponent(LLAP_KEY).getNumberOfContainers() == null ? 0 - : service.getComponent(LLAP_KEY).getNumberOfContainers().intValue()); - appStatusBuilder.setLiveInstances(service.getComponent(LLAP_KEY).getContainers().size()); - for (Container cont : service.getComponent(LLAP_KEY).getContainers()) { - LlapInstance llapInstance = new LlapInstance(cont.getHostname(), cont.getId()); - appStatusBuilder.addNewRunningLlapInstance(llapInstance); - } - if (state == ServiceState.STABLE) { - exitCode = ExitCode.SUCCESS; - } - } else { - exitCode = ExitCode.SERVICE_CLIENT_ERROR_OTHER; - } - } catch (IOException | YarnException e) { - LlapStatusCliException le = new LlapStatusCliException( - LlapStatusServiceDriver.ExitCode.SERVICE_CLIENT_ERROR_OTHER, "Failed to get service status", e); - logError(le); - exitCode = le.getExitCode(); - } - return exitCode; - } - - /** - * 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 - */ - private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBuilder, long watchTimeoutMs) - throws LlapStatusCliException { - - if (llapRegistry == null) { - try { - llapRegistry = LlapRegistryService.getClient(llapRegistryConf); - } catch (Exception e) { - throw new LlapStatusCliException(ExitCode.LLAP_REGISTRY_ERROR, - "Failed to create llap registry client", e); - } - } - - Collection<LlapServiceInstance> serviceInstances; - try { - serviceInstances = llapRegistry.getInstances(watchTimeoutMs).getAll(); - } catch (Exception e) { - throw new LlapStatusCliException(ExitCode.LLAP_REGISTRY_ERROR, "Failed to get instances from llap registry", e); - } - - if (serviceInstances == null || serviceInstances.isEmpty()) { - LOG.debug("No information found in the LLAP registry"); - appStatusBuilder.setLiveInstances(0); - appStatusBuilder.setState(State.LAUNCHING); - appStatusBuilder.clearRunningLlapInstances(); - return ExitCode.SUCCESS; - } else { - // Tracks instances known by both YARN Service and llap. - List<LlapInstance> validatedInstances = new LinkedList<>(); - List<String> llapExtraInstances = new LinkedList<>(); - - for (LlapServiceInstance serviceInstance : serviceInstances) { - String containerIdString = serviceInstance.getProperties().get( - HiveConf.ConfVars.LLAP_DAEMON_CONTAINER_ID.varname); - - LlapInstance llapInstance = appStatusBuilder.removeAndGetRunningLlapInstanceForContainer( - containerIdString); - if (llapInstance != null) { - llapInstance.setMgmtPort(serviceInstance.getManagementPort()); - llapInstance.setRpcPort(serviceInstance.getRpcPort()); - llapInstance.setShufflePort(serviceInstance.getShufflePort()); - llapInstance.setWebUrl(serviceInstance.getServicesAddress()); - llapInstance.setStatusUrl(serviceInstance.getServicesAddress() + "/status"); - validatedInstances.add(llapInstance); - } else { - // This likely indicates that an instance has recently restarted - // (the old instance has not been unregistered), and the new instances has not registered yet. - llapExtraInstances.add(containerIdString); - // This instance will not be added back, since it's services are not up yet. - } - - } - - appStatusBuilder.setLiveInstances(validatedInstances.size()); - appStatusBuilder.setLaunchingInstances(llapExtraInstances.size()); - if (appStatusBuilder.getDesiredInstances() != null && - validatedInstances.size() >= appStatusBuilder.getDesiredInstances()) { - appStatusBuilder.setState(State.RUNNING_ALL); - if (validatedInstances.size() > appStatusBuilder.getDesiredInstances()) { - LOG.warn("Found more entries in LLAP registry, as compared to desired entries"); - } - } else { - if (validatedInstances.size() > 0) { - appStatusBuilder.setState(State.RUNNING_PARTIAL); - } else { - appStatusBuilder.setState(State.LAUNCHING); - } - } - - // At this point, everything that can be consumed from AppStatusBuilder has been consumed. - // Debug only - if (appStatusBuilder.allRunningInstances().size() > 0) { - // Containers likely to come up soon. - LOG.debug("Potential instances starting up: {}", appStatusBuilder.allRunningInstances()); - } - if (llapExtraInstances.size() > 0) { - // Old containers which are likely shutting down, or new containers which - // launched between YARN Service status/diagnostics. Skip for this iteration. - LOG.debug("Instances likely to shutdown soon: {}", llapExtraInstances); - } - - appStatusBuilder.clearAndAddPreviouslyKnownRunningInstances(validatedInstances); - - } - return ExitCode.SUCCESS; - } - - private void close() { - if (serviceClient != null) { - serviceClient.stop(); - } - if (llapRegistry != null) { - llapRegistry.stop(); - } - } - - public enum ExitCode { - SUCCESS(0), - INCORRECT_USAGE(10), - YARN_ERROR(20), - SERVICE_CLIENT_ERROR_CREATE_FAILED(30), - SERVICE_CLIENT_ERROR_OTHER(31), - LLAP_REGISTRY_ERROR(40), - LLAP_JSON_GENERATION_ERROR(50), - // Error in the script itself - likely caused by an incompatible change, or new functionality / states added. - INTERNAL_ERROR(100); - - private final int exitCode; - - ExitCode(int exitCode) { - this.exitCode = exitCode; - } - - public int getInt() { - return exitCode; - } - } - - public static class LlapStatusCliException extends Exception { - final LlapStatusServiceDriver.ExitCode exitCode; - - public LlapStatusCliException(LlapStatusServiceDriver.ExitCode exitCode, String message) { - super(exitCode.getInt() +": " + message); - this.exitCode = exitCode; - } - - public LlapStatusCliException(LlapStatusServiceDriver.ExitCode exitCode, String message, Throwable cause) { - super(exitCode.getInt() +": " + message, cause); - this.exitCode = exitCode; - } - - public LlapStatusServiceDriver.ExitCode getExitCode() { - return exitCode; - } - } - - public static void main(String[] args) { - LOG.info("LLAP status invoked with arguments = {}", Arrays.toString(args)); - int ret = ExitCode.SUCCESS.getInt(); - Clock clock = SystemClock.getInstance(); - long lastSummaryLogTime = -1; - - LlapStatusServiceDriver statusServiceDriver = null; - LlapStatusOptions options = null; - try { - statusServiceDriver = new LlapStatusServiceDriver(); - options = statusServiceDriver.parseOptions(args); - } catch (Throwable t) { - statusServiceDriver.close(); - logError(t); - if (t instanceof LlapStatusCliException) { - LlapStatusCliException ce = (LlapStatusCliException) t; - ret = ce.getExitCode().getInt(); - } else { - ret = ExitCode.INTERNAL_ERROR.getInt(); - } - } - if (ret != 0 || options == null) { // Failure / help - if (statusServiceDriver != null) { - statusServiceDriver.close(); - } - System.exit(ret); - } - - boolean firstAttempt = true; - final long refreshInterval = options.getRefreshIntervalMs(); - final boolean watchMode = options.isWatchMode(); - final long watchTimeout = options.getWatchTimeoutMs(); - long numAttempts = watchTimeout / refreshInterval; - numAttempts = watchMode ? numAttempts : 1; // Break out of the loop fast if watchMode is disabled. - LlapStatusHelpers.State launchingState = null; - LlapStatusHelpers.State currentState = null; - boolean desiredStateAttained = false; - final float runningNodesThreshold = options.getRunningNodesThreshold(); - try (OutputStream os = options.getOutputFile() == null ? System.out : - new BufferedOutputStream(new FileOutputStream(options.getOutputFile())); - PrintWriter pw = new PrintWriter(os)) { - - LOG.info("Configured refresh interval: {}s. Watch timeout: {}s. Attempts remaining: {}." + - " Watch mode: {}. Running nodes threshold: {}.", - TimeUnit.SECONDS.convert(refreshInterval, TimeUnit.MILLISECONDS), - TimeUnit.SECONDS.convert(watchTimeout, TimeUnit.MILLISECONDS), - 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(options, 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.getInt()) { - 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 || options.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.getInt() && watchMode) { - LOG.warn("Watch mode enabled and got YARN error. Retrying.."); - numAttempts--; - continue; - } else if (ret == ExitCode.SERVICE_CLIENT_ERROR_CREATE_FAILED.getInt() && watchMode) { - LOG.warn("Watch mode enabled and YARN Service client creation failed. Retrying.."); - numAttempts--; - continue; - } else if (ret == ExitCode.SERVICE_CLIENT_ERROR_OTHER.getInt() && watchMode) { - LOG.warn("Watch mode enabled and got YARN Service client error. Retrying.."); - numAttempts--; - continue; - } else if (ret == ExitCode.LLAP_REGISTRY_ERROR.getInt() && watchMode) { - LOG.warn("Watch mode enabled and got LLAP registry error. Retrying.."); - numAttempts--; - continue; - } - break; - } - // Log final state to CONSOLE_LOGGER - LlapStatusServiceDriver.maybeLogSummary(clock, 0L, statusServiceDriver, watchMode, watchTimeout, launchingState); - CONSOLE_LOGGER.info("\n\n\n"); - // print current state before exiting - statusServiceDriver.outputJson(pw); - os.flush(); - pw.flush(); - if (numAttempts == 0 && watchMode && !desiredStateAttained) { - LOG.warn("Watch timeout {}s exhausted before desired state RUNNING is attained.", - TimeUnit.SECONDS.convert(watchTimeout, TimeUnit.MILLISECONDS)); - } - } catch (Throwable t) { - logError(t); - if (t instanceof LlapStatusCliException) { - LlapStatusCliException ce = (LlapStatusCliException) t; - ret = ce.getExitCode().getInt(); - } else { - ret = ExitCode.INTERNAL_ERROR.getInt(); - } - } finally { - LOG.info("LLAP status finished"); - if (ret != ExitCode.SUCCESS.exitCode) { - 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); - - System.exit(ret); - } - - private static long maybeLogSummary(Clock clock, long lastSummaryLogTime, LlapStatusServiceDriver statusServiceDriver, - boolean watchMode, long watchTimeout, LlapStatusHelpers.State launchingState) { - long currentTime = clock.getTime(); - if (lastSummaryLogTime < currentTime - LOG_SUMMARY_INTERVAL) { - String diagString = null; - if (launchingState == null && statusServiceDriver.appStatusBuilder.getState() == State.COMPLETE && watchMode) { - // First known state was COMPLETED. Wait for the app launch to start. - diagString = "Awaiting LLAP launch"; - // Clear completed instances in this case. Don't want to provide information from the previous run. - statusServiceDriver.appStatusBuilder.clearCompletedLlapInstances(); - } else { - diagString = constructDiagnostics(statusServiceDriver.appStatusBuilder); - } - - if (lastSummaryLogTime == -1) { - if (watchMode) { - CONSOLE_LOGGER.info("\nLLAPSTATUS WatchMode with timeout={} s", - TimeUnit.SECONDS.convert(watchTimeout, TimeUnit.MILLISECONDS)); - } else { - CONSOLE_LOGGER.info("\nLLAPSTATUS"); - } - CONSOLE_LOGGER.info("--------------------------------------------------------------------------------"); - } - CONSOLE_LOGGER.info(diagString); - CONSOLE_LOGGER.info("--------------------------------------------------------------------------------"); - lastSummaryLogTime = currentTime; - } - return lastSummaryLogTime; - } - - /** - * Helper method to construct a diagnostic message from a complete AppStatusBuilder. - */ - private static String constructDiagnostics(AppStatusBuilder appStatusBuilder) { - StringBuilder sb = new StringBuilder(); - - switch (appStatusBuilder.getState()) { - case APP_NOT_FOUND: - sb.append("LLAP status unknown. Awaiting app launch"); - break; - case LAUNCHING: - // This is a catch all state - when containers have not started yet, or LLAP has not started yet. - if (StringUtils.isNotBlank(appStatusBuilder.getAmInfo().getAppId())) { - sb.append("LLAP Starting up with AppId=").append(appStatusBuilder.getAmInfo().getAppId()).append("."); - if (appStatusBuilder.getDesiredInstances() != null) { - sb.append(" Started 0/").append(appStatusBuilder.getDesiredInstances()).append(" instances"); - } - - String containerDiagnostics = constructCompletedContainerDiagnostics( - appStatusBuilder.getCompletedInstances()); - if (StringUtils.isNotEmpty(containerDiagnostics)) { - sb.append("\n").append(containerDiagnostics); - } - } else { - sb.append("Awaiting LLAP startup"); - } - break; - case RUNNING_PARTIAL: - sb.append("LLAP Starting up with ApplicationId=").append(appStatusBuilder.getAmInfo().getAppId()); - sb.append(" Started").append(appStatusBuilder.getLiveInstances()).append("/") - .append(appStatusBuilder.getDesiredInstances()).append(" instances"); - String containerDiagnostics = constructCompletedContainerDiagnostics(appStatusBuilder.getCompletedInstances()); - if (StringUtils.isNotEmpty(containerDiagnostics)) { - sb.append("\n").append(containerDiagnostics); - } - - // TODO HIVE-15865: Include information about pending requests, and last - // allocation time once YARN Service provides this information. - break; - case RUNNING_ALL: - sb.append("LLAP Application running with ApplicationId=").append(appStatusBuilder.getAmInfo().getAppId()); - break; - case COMPLETE: - sb.append("LLAP Application already complete. ApplicationId=").append(appStatusBuilder.getAmInfo().getAppId()); - containerDiagnostics = constructCompletedContainerDiagnostics(appStatusBuilder.getCompletedInstances()); - if (StringUtils.isNotEmpty(containerDiagnostics)) { - sb.append("\n").append(containerDiagnostics); - } - - break; - case UNKNOWN: - sb.append("LLAP status unknown"); - break; - } - if (StringUtils.isNotBlank(appStatusBuilder.getDiagnostics())) { - sb.append("\n").append(appStatusBuilder.getDiagnostics()); - } - - return sb.toString(); - } - - private static String constructCompletedContainerDiagnostics(List<LlapInstance> completedInstances) { - StringBuilder sb = new StringBuilder(); - if (completedInstances == null || completedInstances.size() == 0) { - return ""; - } else { - // TODO HIVE-15865 Ideally sort these by completion time, once that is available. - boolean isFirst = true; - for (LlapInstance instance : completedInstances) { - if (!isFirst) { - sb.append("\n"); - } else { - isFirst = false; - } - - if (instance.getYarnContainerExitStatus() == ContainerExitStatus.KILLED_EXCEEDED_PMEM || - instance.getYarnContainerExitStatus() == ContainerExitStatus.KILLED_EXCEEDED_VMEM) { - sb.append("\tKILLED container (by YARN for exceeding memory limits): "); - } else { - // TODO HIVE-15865 Handle additional reasons like OS launch failed - sb.append("\tFAILED container: "); - } - sb.append(" ").append(instance.getContainerId()); - sb.append(", Logs at: ").append(instance.getLogUrl()); - } - } - return sb.toString(); - } - - private static void logError(Throwable t) { - LOG.error("FAILED: " + t.getMessage(), t); - System.err.println("FAILED: " + t.getMessage()); - } -} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AmInfo.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AmInfo.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AmInfo.java new file mode 100644 index 0000000..ac2ff65 --- /dev/null +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AmInfo.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.llap.cli.status; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Represents the state of the yarn application. + */ +class AmInfo { + private String appName; + private String appType; + private String appId; + private String containerId; + private String hostname; + private String amWebUrl; + + AmInfo setAppName(String appName) { + this.appName = appName; + return this; + } + + AmInfo setAppType(String appType) { + this.appType = appType; + return this; + } + + AmInfo setAppId(String appId) { + this.appId = appId; + return this; + } + + AmInfo setContainerId(String containerId) { + this.containerId = containerId; + return this; + } + + AmInfo setHostname(String hostname) { + this.hostname = hostname; + return this; + } + + AmInfo setAmWebUrl(String amWebUrl) { + this.amWebUrl = amWebUrl; + return this; + } + + String getAppName() { + return appName; + } + + String getAppType() { + return appType; + } + + String getAppId() { + return appId; + } + + String getContainerId() { + return containerId; + } + + String getHostname() { + return hostname; + } + + String getAmWebUrl() { + return amWebUrl; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AppStatusBuilder.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AppStatusBuilder.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AppStatusBuilder.java new file mode 100644 index 0000000..c2ba4db --- /dev/null +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/AppStatusBuilder.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.llap.cli.status; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.codehaus.jackson.annotate.JsonIgnore; + +/** + * Represents the status of the Llap application. + */ +class AppStatusBuilder { + + private AmInfo amInfo; + private State state = State.UNKNOWN; + private String diagnostics; + private String originalConfigurationPath; + private String generatedConfigurationPath; + + private Long appStartTime; + private Long appFinishTime; + + private boolean runningThresholdAchieved = false; + + private Integer desiredInstances = null; + private Integer liveInstances = null; + private Integer launchingInstances = null; + + private final List<LlapInstance> runningInstances = new LinkedList<>(); + private final List<LlapInstance> completedInstances = new LinkedList<>(); + + private final transient Map<String, LlapInstance> containerToRunningInstanceMap = new HashMap<>(); + private final transient Map<String, LlapInstance> containerToCompletedInstanceMap = new HashMap<>(); + + void setAmInfo(AmInfo amInfo) { + this.amInfo = amInfo; + } + + AppStatusBuilder setState(State state) { + this.state = state; + return this; + } + + AppStatusBuilder setDiagnostics(String diagnostics) { + this.diagnostics = diagnostics; + return this; + } + + AppStatusBuilder setOriginalConfigurationPath(String originalConfigurationPath) { + this.originalConfigurationPath = originalConfigurationPath; + return this; + } + + AppStatusBuilder setGeneratedConfigurationPath(String generatedConfigurationPath) { + this.generatedConfigurationPath = generatedConfigurationPath; + return this; + } + + AppStatusBuilder setAppStartTime(long appStartTime) { + this.appStartTime = appStartTime; + return this; + } + + AppStatusBuilder setAppFinishTime(long finishTime) { + this.appFinishTime = finishTime; + return this; + } + + void setRunningThresholdAchieved(boolean runningThresholdAchieved) { + this.runningThresholdAchieved = runningThresholdAchieved; + } + + AppStatusBuilder setDesiredInstances(int desiredInstances) { + this.desiredInstances = desiredInstances; + return this; + } + + AppStatusBuilder setLiveInstances(int liveInstances) { + this.liveInstances = liveInstances; + return this; + } + + AppStatusBuilder setLaunchingInstances(int launchingInstances) { + this.launchingInstances = launchingInstances; + return this; + } + + AppStatusBuilder addNewRunningLlapInstance(LlapInstance llapInstance) { + this.runningInstances.add(llapInstance); + this.containerToRunningInstanceMap + .put(llapInstance.getContainerId(), llapInstance); + return this; + } + + LlapInstance removeAndGetRunningLlapInstanceForContainer(String containerIdString) { + return containerToRunningInstanceMap.remove(containerIdString); + } + + void clearRunningLlapInstances() { + this.runningInstances.clear(); + this.containerToRunningInstanceMap.clear(); + } + + AppStatusBuilder clearAndAddPreviouslyKnownRunningInstances(List<LlapInstance> llapInstances) { + clearRunningLlapInstances(); + for (LlapInstance llapInstance : llapInstances) { + addNewRunningLlapInstance(llapInstance); + } + return this; + } + + @JsonIgnore + List<LlapInstance> allRunningInstances() { + return this.runningInstances; + } + + AppStatusBuilder addNewCompleteLlapInstance(LlapInstance llapInstance) { + this.completedInstances.add(llapInstance); + this.containerToCompletedInstanceMap + .put(llapInstance.getContainerId(), llapInstance); + return this; + } + + LlapInstance removeAndGetCompletedLlapInstanceForContainer(String containerIdString) { + return containerToCompletedInstanceMap.remove(containerIdString); + } + + void clearCompletedLlapInstances() { + this.completedInstances.clear(); + this.containerToCompletedInstanceMap.clear(); + } + + AppStatusBuilder clearAndAddPreviouslyKnownCompletedInstances(List<LlapInstance> llapInstances) { + clearCompletedLlapInstances(); + for (LlapInstance llapInstance : llapInstances) { + addNewCompleteLlapInstance(llapInstance); + } + return this; + } + + @JsonIgnore + List<LlapInstance> allCompletedInstances() { + return this.completedInstances; + } + + AmInfo getAmInfo() { + return amInfo; + } + + State getState() { + return state; + } + + String getDiagnostics() { + return diagnostics; + } + + String getOriginalConfigurationPath() { + return originalConfigurationPath; + } + + String getGeneratedConfigurationPath() { + return generatedConfigurationPath; + } + + Long getAppStartTime() { + return appStartTime; + } + + Long getAppFinishTime() { + return appFinishTime; + } + + boolean isRunningThresholdAchieved() { + return runningThresholdAchieved; + } + + Integer getDesiredInstances() { + return desiredInstances; + } + + Integer getLiveInstances() { + return liveInstances; + } + + Integer getLaunchingInstances() { + return launchingInstances; + } + + List<LlapInstance> getRunningInstances() { + return runningInstances; + } + + List<LlapInstance> getCompletedInstances() { + return completedInstances; + } + + @JsonIgnore + AmInfo maybeCreateAndGetAmInfo() { + if (amInfo == null) { + amInfo = new AmInfo(); + } + return amInfo; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/ExitCode.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/ExitCode.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/ExitCode.java new file mode 100644 index 0000000..16c71d2 --- /dev/null +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/ExitCode.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.llap.cli.status; + +/** + * Enumeration of the potential outcomes of the Llap state checking. + */ +public enum ExitCode { + SUCCESS(0), + INCORRECT_USAGE(10), + YARN_ERROR(20), + SERVICE_CLIENT_ERROR_CREATE_FAILED(30), + SERVICE_CLIENT_ERROR_OTHER(31), + LLAP_REGISTRY_ERROR(40), + LLAP_JSON_GENERATION_ERROR(50), + // Error in the script itself - likely caused by an incompatible change, or new functionality / states added. + INTERNAL_ERROR(100); + + private final int code; + + ExitCode(int code) { + this.code = code; + } + + public int getCode() { + return code; + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapInstance.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapInstance.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapInstance.java new file mode 100644 index 0000000..5b979fd --- /dev/null +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapInstance.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.llap.cli.status; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Representing the state of an Llap instance monitored. + */ +class LlapInstance { + private final String hostname; + private final String containerId; + private String logUrl; + + // Only for live instances. + private String statusUrl; + private String webUrl; + private Integer rpcPort; + private Integer mgmtPort; + private Integer shufflePort; + + // For completed instances + private String diagnostics; + private int yarnContainerExitStatus; + + // TODO HIVE-13454 Add additional information such as #executors, container size, etc + + LlapInstance(String hostname, String containerId) { + this.hostname = hostname; + this.containerId = containerId; + } + + LlapInstance setLogUrl(String logUrl) { + this.logUrl = logUrl; + return this; + } + + LlapInstance setStatusUrl(String statusUrl) { + this.statusUrl = statusUrl; + return this; + } + + LlapInstance setWebUrl(String webUrl) { + this.webUrl = webUrl; + return this; + } + + LlapInstance setRpcPort(int rpcPort) { + this.rpcPort = rpcPort; + return this; + } + + LlapInstance setMgmtPort(int mgmtPort) { + this.mgmtPort = mgmtPort; + return this; + } + + LlapInstance setShufflePort(int shufflePort) { + this.shufflePort = shufflePort; + return this; + } + + LlapInstance setDiagnostics(String diagnostics) { + this.diagnostics = diagnostics; + return this; + } + + LlapInstance setYarnContainerExitStatus(int yarnContainerExitStatus) { + this.yarnContainerExitStatus = yarnContainerExitStatus; + return this; + } + + String getHostname() { + return hostname; + } + + String getContainerId() { + return containerId; + } + + String getLogUrl() { + return logUrl; + } + + String getStatusUrl() { + return statusUrl; + } + + String getWebUrl() { + return webUrl; + } + + Integer getRpcPort() { + return rpcPort; + } + + Integer getMgmtPort() { + return mgmtPort; + } + + Integer getShufflePort() { + return shufflePort; + } + + String getDiagnostics() { + return diagnostics; + } + + int getYarnContainerExitStatus() { + return yarnContainerExitStatus; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusCliException.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusCliException.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusCliException.java new file mode 100644 index 0000000..7ebf404 --- /dev/null +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusCliException.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.llap.cli.status; + +/** + * Representing the exceptions that may occur during the Llap state chacking. + */ +class LlapStatusCliException extends Exception { + private final ExitCode exitCode; + + LlapStatusCliException(ExitCode exitCode, String message) { + super(exitCode.getCode() +": " + message); + this.exitCode = exitCode; + } + + LlapStatusCliException(ExitCode exitCode, String message, Throwable cause) { + super(exitCode.getCode() +": " + message, cause); + this.exitCode = exitCode; + } + + ExitCode getExitCode() { + return exitCode; + } +} http://git-wip-us.apache.org/repos/asf/hive/blob/af401702/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusHelpers.java ---------------------------------------------------------------------- diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusHelpers.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusHelpers.java deleted file mode 100644 index 5c8aeb0..0000000 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusHelpers.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hive.llap.cli.status; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.hadoop.hive.llap.cli.LlapStatusServiceDriver; -import org.codehaus.jackson.annotate.JsonIgnore; - -public class LlapStatusHelpers { - public enum State { - APP_NOT_FOUND, LAUNCHING, - RUNNING_PARTIAL, - RUNNING_ALL, COMPLETE, UNKNOWN - } - - public static class AmInfo { - private String appName; - private String appType; - private String appId; - private String containerId; - private String hostname; - private String amWebUrl; - - public AmInfo setAppName(String appName) { - this.appName = appName; - return this; - } - - public AmInfo setAppType(String appType) { - this.appType = appType; - return this; - } - - public AmInfo setAppId(String appId) { - this.appId = appId; - return this; - } - - public AmInfo setContainerId(String containerId) { - this.containerId = containerId; - return this; - } - - public AmInfo setHostname(String hostname) { - this.hostname = hostname; - return this; - } - - public AmInfo setAmWebUrl(String amWebUrl) { - this.amWebUrl = amWebUrl; - return this; - } - - public String getAppName() { - return appName; - } - - public String getAppType() { - return appType; - } - - public String getAppId() { - return appId; - } - - public String getContainerId() { - return containerId; - } - - public String getHostname() { - return hostname; - } - - public String getAmWebUrl() { - return amWebUrl; - } - - @Override - public String toString() { - return "AmInfo{" + - "appName='" + appName + '\'' + - ", appType='" + appType + '\'' + - ", appId='" + appId + '\'' + - ", containerId='" + containerId + '\'' + - ", hostname='" + hostname + '\'' + - ", amWebUrl='" + amWebUrl + '\'' + - '}'; - } - } - - public static class LlapInstance { - private final String hostname; - private final String containerId; - private String logUrl; - - // Only for live instances. - private String statusUrl; - private String webUrl; - private Integer rpcPort; - private Integer mgmtPort; - private Integer shufflePort; - - // For completed instances - private String diagnostics; - private int yarnContainerExitStatus; - - // TODO HIVE-13454 Add additional information such as #executors, container size, etc - - public LlapInstance(String hostname, String containerId) { - this.hostname = hostname; - this.containerId = containerId; - } - - public LlapInstance setLogUrl(String logUrl) { - this.logUrl = logUrl; - return this; - } - - public LlapInstance setWebUrl(String webUrl) { - this.webUrl = webUrl; - return this; - } - - public LlapInstance setStatusUrl(String statusUrl) { - this.statusUrl = statusUrl; - return this; - } - - public LlapInstance setRpcPort(int rpcPort) { - this.rpcPort = rpcPort; - return this; - } - - public LlapInstance setMgmtPort(int mgmtPort) { - this.mgmtPort = mgmtPort; - return this; - } - - public LlapInstance setShufflePort(int shufflePort) { - this.shufflePort = shufflePort; - return this; - } - - public LlapInstance setDiagnostics(String diagnostics) { - this.diagnostics = diagnostics; - return this; - } - - public LlapInstance setYarnContainerExitStatus(int yarnContainerExitStatus) { - this.yarnContainerExitStatus = yarnContainerExitStatus; - return this; - } - - public String getHostname() { - return hostname; - } - - public String getLogUrl() { - return logUrl; - } - - public String getStatusUrl() { - return statusUrl; - } - - public String getContainerId() { - return containerId; - } - - public String getWebUrl() { - return webUrl; - } - - public Integer getRpcPort() { - return rpcPort; - } - - public Integer getMgmtPort() { - return mgmtPort; - } - - public Integer getShufflePort() { - return shufflePort; - } - - public String getDiagnostics() { - return diagnostics; - } - - public int getYarnContainerExitStatus() { - return yarnContainerExitStatus; - } - - @Override - public String toString() { - return "LlapInstance{" + - "hostname='" + hostname + '\'' + - "logUrl=" + logUrl + '\'' + - ", containerId='" + containerId + '\'' + - ", statusUrl='" + statusUrl + '\'' + - ", webUrl='" + webUrl + '\'' + - ", rpcPort=" + rpcPort + - ", mgmtPort=" + mgmtPort + - ", shufflePort=" + shufflePort + - ", diagnostics=" + diagnostics + - ", yarnContainerExitStatus=" + yarnContainerExitStatus + - '}'; - } - } - - public static final class AppStatusBuilder { - - private AmInfo amInfo; - private State state = State.UNKNOWN; - private String diagnostics; - private String originalConfigurationPath; - private String generatedConfigurationPath; - - private Integer desiredInstances = null; - private Integer liveInstances = null; - private Integer launchingInstances = null; - - - private Long appStartTime; - private Long appFinishTime; - - private boolean runningThresholdAchieved = false; - - private final List<LlapInstance> runningInstances = new LinkedList<>(); - private final List<LlapInstance> completedInstances = new LinkedList<>(); - - private transient final Map<String, LlapInstance> - containerToRunningInstanceMap = new HashMap<>(); - private transient final Map<String, LlapInstance> - containerToCompletedInstanceMap = new HashMap<>(); - - public void setAmInfo(AmInfo amInfo) { - this.amInfo = amInfo; - } - - public AppStatusBuilder setState( - State state) { - this.state = state; - return this; - } - - public AppStatusBuilder setDiagnostics(String diagnostics) { - this.diagnostics = diagnostics; - return this; - } - - public AppStatusBuilder setOriginalConfigurationPath(String originalConfigurationPath) { - this.originalConfigurationPath = originalConfigurationPath; - return this; - } - - public AppStatusBuilder setGeneratedConfigurationPath(String generatedConfigurationPath) { - this.generatedConfigurationPath = generatedConfigurationPath; - return this; - } - - public AppStatusBuilder setAppStartTime(long appStartTime) { - this.appStartTime = appStartTime; - return this; - } - - public AppStatusBuilder setAppFinishTime(long finishTime) { - this.appFinishTime = finishTime; - return this; - } - - public void setRunningThresholdAchieved(boolean runningThresholdAchieved) { - this.runningThresholdAchieved = runningThresholdAchieved; - } - - public AppStatusBuilder setDesiredInstances(int desiredInstances) { - this.desiredInstances = desiredInstances; - return this; - } - - public AppStatusBuilder setLiveInstances(int liveInstances) { - this.liveInstances = liveInstances; - return this; - } - - public AppStatusBuilder setLaunchingInstances(int launchingInstances) { - this.launchingInstances = launchingInstances; - return this; - } - - public AppStatusBuilder addNewRunningLlapInstance(LlapInstance llapInstance) { - this.runningInstances.add(llapInstance); - this.containerToRunningInstanceMap - .put(llapInstance.getContainerId(), llapInstance); - return this; - } - - public LlapInstance removeAndGetRunningLlapInstanceForContainer(String containerIdString) { - return containerToRunningInstanceMap.remove(containerIdString); - } - - public void clearRunningLlapInstances() { - this.runningInstances.clear(); - this.containerToRunningInstanceMap.clear(); - } - - public AppStatusBuilder clearAndAddPreviouslyKnownRunningInstances(List<LlapInstance> llapInstances) { - clearRunningLlapInstances(); - for (LlapInstance llapInstance : llapInstances) { - addNewRunningLlapInstance(llapInstance); - } - return this; - } - - @JsonIgnore - public List<LlapInstance> allRunningInstances() { - return this.runningInstances; - } - - public AppStatusBuilder addNewCompleteLlapInstance(LlapInstance llapInstance) { - this.completedInstances.add(llapInstance); - this.containerToCompletedInstanceMap - .put(llapInstance.getContainerId(), llapInstance); - return this; - } - - public LlapInstance removeAndGetCompletedLlapInstanceForContainer(String containerIdString) { - return containerToCompletedInstanceMap.remove(containerIdString); - } - - public void clearCompletedLlapInstances() { - this.completedInstances.clear(); - this.containerToCompletedInstanceMap.clear(); - } - - public AppStatusBuilder clearAndAddPreviouslyKnownCompletedInstances(List<LlapInstance> llapInstances) { - clearCompletedLlapInstances(); - for (LlapInstance llapInstance : llapInstances) { - addNewCompleteLlapInstance(llapInstance); - } - return this; - } - - @JsonIgnore - public List<LlapInstance> allCompletedInstances() { - return this.completedInstances; - } - - public AmInfo getAmInfo() { - return amInfo; - } - - public State getState() { - return state; - } - - public String getDiagnostics() { - return diagnostics; - } - - public String getOriginalConfigurationPath() { - return originalConfigurationPath; - } - - public String getGeneratedConfigurationPath() { - return generatedConfigurationPath; - } - - public Integer getDesiredInstances() { - return desiredInstances; - } - - public Integer getLiveInstances() { - return liveInstances; - } - - public Integer getLaunchingInstances() { - return launchingInstances; - } - - public Long getAppStartTime() { - return appStartTime; - } - - public Long getAppFinishTime() { - return appFinishTime; - } - - public boolean isRunningThresholdAchieved() { - return runningThresholdAchieved; - } - - public List<LlapInstance> getRunningInstances() { - return runningInstances; - } - - public List<LlapInstance> getCompletedInstances() { - return completedInstances; - } - - @JsonIgnore - public AmInfo maybeCreateAndGetAmInfo() { - if (amInfo == null) { - amInfo = new AmInfo(); - } - return amInfo; - } - - @Override - public String toString() { - return "AppStatusBuilder{" + - "amInfo=" + amInfo + - ", state=" + state + - ", diagnostics=" + diagnostics + - ", originalConfigurationPath='" + originalConfigurationPath + '\'' + - ", generatedConfigurationPath='" + generatedConfigurationPath + '\'' + - ", desiredInstances=" + desiredInstances + - ", liveInstances=" + liveInstances + - ", launchingInstances=" + launchingInstances + - ", appStartTime=" + appStartTime + - ", appFinishTime=" + appFinishTime + - ", runningThresholdAchieved=" + runningThresholdAchieved + - ", runningInstances=" + runningInstances + - ", completedInstances=" + completedInstances + - ", containerToRunningInstanceMap=" + containerToRunningInstanceMap + - '}'; - } - } -}