diff --git a/.travis.yml b/.asf.yaml
similarity index 63%
rename from .travis.yml
rename to .asf.yaml
index bfc6b34bbf..776f8a6f7c 100644
--- a/.travis.yml
+++ b/.asf.yaml
@@ -14,18 +14,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-language: java
-
-sudo: required
-
-env: MAVEN_OPTS="-Xmx2G -XX:MaxPermSize=512M"
-
-jdk:
- - oraclejdk8
-
-before_install:
- - ./build-tools/install-protobuf.sh
-
-script:
- - mvn -B clean install package -DskipTests=true -Dmaven.javadoc.skip=true
-
+github:
+ description: "Apache Tez"
+ homepage: https://tez.apache.org/
+ labels:
+ - tez
+ - java
+ - apache
+ - big-data
+ - hadoop
+ features:
+ wiki: false
+ issues: false
+ projects: false
+ enabled_merge_buttons:
+ squash: true
+ merge: false
+ rebase: false
+notifications:
+ commits: commits@tez.apache.org
+ issues: issues@tez.apache.org
+ pullrequests: issues@tez.apache.org
+ jira_options: link label worklog
diff --git a/build-tools/install-protobuf.sh b/.github/workflows/build.yml
old mode 100755
new mode 100644
similarity index 60%
rename from build-tools/install-protobuf.sh
rename to .github/workflows/build.yml
index 902049dab1..f81c1ad8b1
--- a/build-tools/install-protobuf.sh
+++ b/.github/workflows/build.yml
@@ -1,5 +1,3 @@
-#!/bin/sh
-
# 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
@@ -15,8 +13,26 @@
# 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.
+name: Build CI with different platforms/configs
+
+on:
+ push:
+ branches:
+ - 'master'
+ pull_request:
+ branches:
+ - 'master'
-set -ex
-wget https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz
-tar -xzvf protobuf-2.5.0.tar.gz
-cd protobuf-2.5.0 && ./configure --prefix=/usr && make && sudo make install
+jobs:
+ build:
+ strategy:
+ matrix:
+ java-version: [8, 11, 17]
+ os: [ubuntu-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-java@v1
+ with:
+ java-version: ${{ matrix.java-version }}
+ - run: mvn clean install -DskipTests -Dmaven.javadoc.skip=true
diff --git a/.gitignore b/.gitignore
index 01c99576d6..85d660672c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.ipr
*.iws
*.DS_Store
+*.pyc
.idea
.svn
.classpath
diff --git a/BUILDING.txt b/BUILDING.txt
index 34ed2fbff1..57c9cd13c0 100644
--- a/BUILDING.txt
+++ b/BUILDING.txt
@@ -6,10 +6,10 @@ https://cwiki.apache.org/confluence/display/TEZ
----------------------------------------------------------------------------------
Requirements:
-* JDK 1.7+
-* Maven 3.1 or later
+* JDK 1.8+
+* Maven 3.6.3 or later
* Findbugs 2.0.2 or later (if running findbugs)
-* ProtocolBuffer 2.5.0
+* ProtocolBuffer 3.21.1
* Internet connection for first build (to fetch all dependencies)
* Hadoop version should be 2.7.0 or higher.
@@ -52,6 +52,7 @@ Build options:
* Use -Dclover.license to specify the path to the clover license file
* Use -Dhadoop.version to specify the version of hadoop to build tez against
* Use -Dprotoc.path to specify the path to protoc
+ * Use -Dallow.root.build to root build tez-ui components
Tests options:
@@ -103,16 +104,29 @@ Issue with PhantomJS on building in PowerPC.
please try installing PhantomJS manually and rerun. Refer https://github.com/ibmsoe/phantomjs-1/blob/v2.1.1-ppc64/README.md
and install it globally for the build to work.
+----------------------------------------------------------------------------------
+Skip UI build:
+
+In case you want to completely skip UI build, you can use 'noui' profile.
+For instance, a full build without tests and tez-ui looks like:
+
+ $ mvn clean install -DskipTests -Pnoui
+
+It's important to note that maven will still include tez-ui project, but all of the maven plugins are skipped.
+
----------------------------------------------------------------------------------
Protocol Buffer compiler:
-The version of Protocol Buffer compiler, protoc, must be 2.5.0 and match the
-version of the protobuf JAR.
+The version of Protocol Buffer compiler, protoc, can be defined on-the-fly as:
+ $ mvn clean install -DskipTests -pl ./tez-api -Dprotobuf.version=3.7.1
+
+The default version is defined in the root pom.xml.
-If you have multiple versions of protoc in your system, you can set in your
-build shell the PROTOC_PATH environment variable to point to the one you
-want to use for the Tez build. If you don't define this environment variable,
-protoc is looked up in the PATH.
+If you have multiple versions of protoc in your system, you can set in your
+build shell the PROTOC_PATH environment variable to point to the one you
+want to use for the Tez build. If you don't define this environment variable then the
+embedded protoc compiler will be used with the version defined in ${protobuf.version}.
+It detects the platform and executes the corresponding protoc binary at build time.
You can also specify the path to protoc while building using -Dprotoc.path
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000000..4ce236598d
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,215 @@
+// 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.
+
+pipeline {
+
+ agent {
+ label 'Hadoop'
+ }
+
+ options {
+ buildDiscarder(logRotator(numToKeepStr: '5'))
+ timeout (time: 20, unit: 'HOURS')
+ timestamps()
+ checkoutToSubdirectory('src')
+ }
+
+ environment {
+ SOURCEDIR = 'src'
+ // will also need to change notification section below
+ PATCHDIR = 'out'
+ DOCKERFILE = "${SOURCEDIR}/build-tools/docker/Dockerfile"
+ YETUS='yetus'
+ // Branch or tag name. Yetus release tags are 'rel/X.Y.Z'
+ YETUS_VERSION='rel/0.12.0'
+
+ }
+
+ parameters {
+ string(name: 'JIRA_ISSUE_KEY',
+ defaultValue: '',
+ description: 'The JIRA issue that has a patch needing pre-commit testing. Example: HADOOP-1234')
+ }
+
+ stages {
+ stage ('install yetus') {
+ steps {
+ dir("${WORKSPACE}/${YETUS}") {
+ checkout([
+ $class: 'GitSCM',
+ branches: [[name: "${env.YETUS_VERSION}"]],
+ userRemoteConfigs: [[ url: 'https://github.com/apache/yetus']]]
+ )
+ }
+ }
+ }
+
+ stage ('precommit-run') {
+ steps {
+ withCredentials(
+ [usernamePassword(credentialsId: 'apache-tez-at-github.com',
+ passwordVariable: 'GITHUB_TOKEN',
+ usernameVariable: 'GITHUB_USER'),
+ usernamePassword(credentialsId: 'tez-ci',
+ passwordVariable: 'JIRA_PASSWORD',
+ usernameVariable: 'JIRA_USER')]) {
+ sh '''#!/usr/bin/env bash
+
+ set -e
+
+ TESTPATCHBIN="${WORKSPACE}/${YETUS}/precommit/src/main/shell/test-patch.sh"
+
+ # this must be clean for every run
+ if [[ -d "${WORKSPACE}/${PATCHDIR}" ]]; then
+ rm -rf "${WORKSPACE}/${PATCHDIR}"
+ fi
+ mkdir -p "${WORKSPACE}/${PATCHDIR}"
+
+ # if given a JIRA issue, process it. If CHANGE_URL is set
+ # (e.g., Github Branch Source plugin), process it.
+ # otherwise exit, because we don't want Hadoop to do a
+ # full build. We wouldn't normally do this check for smaller
+ # projects. :)
+ if [[ -n "${JIRA_ISSUE_KEY}" ]]; then
+ YETUS_ARGS+=("${JIRA_ISSUE_KEY}")
+ elif [[ -z "${CHANGE_URL}" ]]; then
+ echo "Full build skipped" > "${WORKSPACE}/${PATCHDIR}/report.html"
+ exit 0
+ fi
+
+ YETUS_ARGS+=("--patch-dir=${WORKSPACE}/${PATCHDIR}")
+
+ # where the source is located
+ YETUS_ARGS+=("--basedir=${WORKSPACE}/${SOURCEDIR}")
+
+ # our project defaults come from a personality file
+ YETUS_ARGS+=("--project=tez")
+
+ # lots of different output formats
+ YETUS_ARGS+=("--brief-report-file=${WORKSPACE}/${PATCHDIR}/brief.txt")
+ YETUS_ARGS+=("--console-report-file=${WORKSPACE}/${PATCHDIR}/console.txt")
+ YETUS_ARGS+=("--html-report-file=${WORKSPACE}/${PATCHDIR}/report.html")
+
+ # enable writing back to Github
+ YETUS_ARGS+=(--github-user="${GITHUB_USER}")
+ YETUS_ARGS+=(--github-token="${GITHUB_TOKEN}")
+
+ # auto-kill any surefire stragglers during unit test runs
+ YETUS_ARGS+=("--reapermode=kill")
+
+ # set relatively high limits for ASF machines
+ # changing these to higher values may cause problems
+ # with other jobs on systemd-enabled machines
+ YETUS_ARGS+=("--proclimit=5500")
+ YETUS_ARGS+=("--dockermemlimit=20g")
+
+ # -1 findbugs issues that show up prior to the patch being applied
+ # YETUS_ARGS+=("--findbugs-strict-precheck")
+
+ # rsync these files back into the archive dir
+ YETUS_ARGS+=("--archive-list=checkstyle-errors.xml,findbugsXml.xml")
+
+ # URL for user-side presentation in reports and such to our artifacts
+ # (needs to match the archive bits below)
+ YETUS_ARGS+=("--build-url-artifacts=artifact/out")
+
+ # plugins to enable
+ YETUS_ARGS+=("--plugins=all")
+
+ # use Hadoop's bundled shelldocs
+ YETUS_ARGS+=("--shelldocs=${WORKSPACE}/${SOURCEDIR}/dev-support/bin/shelldocs")
+
+ # don't let these tests cause -1s because we aren't really paying that
+ # much attention to them
+ YETUS_ARGS+=("--tests-filter=checkstyle")
+
+ # run in docker mode and specifically point to our
+ # Dockerfile since we don't want to use the auto-pulled version.
+ YETUS_ARGS+=("--docker")
+ YETUS_ARGS+=("--dockerfile=${DOCKERFILE}")
+ YETUS_ARGS+=("--mvn-custom-repos")
+
+ # effectively treat dev-suport as a custom maven module
+ YETUS_ARGS+=("--skip-dirs=dev-support")
+
+ # help keep the ASF boxes clean
+ YETUS_ARGS+=("--sentinel")
+
+ # use emoji vote so it is easier to find the broken line
+ YETUS_ARGS+=("--github-use-emoji-vote")
+
+ # test with Java 8 and 11
+ YETUS_ARGS+=("--java-home=/usr/lib/jvm/java-8-openjdk-amd64")
+ YETUS_ARGS+=("--multijdkdirs=/usr/lib/jvm/java-11-openjdk-amd64")
+ YETUS_ARGS+=("--multijdktests=compile")
+ YETUS_ARGS+=("--debug")
+
+ "${TESTPATCHBIN}" "${YETUS_ARGS[@]}"
+ '''
+ }
+ }
+ }
+
+ }
+
+ post {
+ always {
+ script {
+ // Yetus output
+ archiveArtifacts "${env.PATCHDIR}/**"
+ // Publish the HTML report so that it can be looked at
+ // Has to be relative to WORKSPACE.
+ publishHTML (target: [
+ allowMissing: true,
+ keepAll: true,
+ alwaysLinkToLastBuild: true,
+ // Has to be relative to WORKSPACE
+ reportDir: "${env.PATCHDIR}",
+ reportFiles: 'report.html',
+ reportName: 'Yetus Report'
+ ])
+ // Publish JUnit results
+ try {
+ junit "${env.SOURCEDIR}/**/target/surefire-reports/*.xml"
+ } catch(e) {
+ echo 'junit processing: ' + e.toString()
+ }
+ }
+ }
+
+ // Jenkins pipeline jobs fill slaves on PRs without this :(
+ cleanup() {
+ script {
+ sh '''
+ # See YETUS-764
+ if [ -f "${WORKSPACE}/${PATCHDIR}/pidfile.txt" ]; then
+ echo "test-patch process appears to still be running: killing"
+ kill `cat "${WORKSPACE}/${PATCHDIR}/pidfile.txt"` || true
+ sleep 10
+ fi
+ if [ -f "${WORKSPACE}/${PATCHDIR}/cidfile.txt" ]; then
+ echo "test-patch container appears to still be running: killing"
+ docker kill `cat "${WORKSPACE}/${PATCHDIR}/cidfile.txt"` || true
+ fi
+ # See HADOOP-13951
+ chmod -R u+rxw "${WORKSPACE}"
+ '''
+ deleteDir()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/KEYS b/KEYS
deleted file mode 100644
index 6485099611..0000000000
--- a/KEYS
+++ /dev/null
@@ -1,417 +0,0 @@
-pub 4096R/F0B000F0 2013-06-16
- Key fingerprint = EB34 498A 9261 F343 F09F 60E0 A951 0905 F0B0 00F0
-uid Hitesh Shah
-sub 4096R/A64C68A3 2013-06-16
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v2.0.19 (Darwin)
-
-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
-stAukccPZ/ir4OIk
-=P10A
------END PGP PUBLIC KEY BLOCK-----
-pub 4096R/3DD51430 2014-03-30
- Key fingerprint = A13B 3869 4545 36F1 852C 17D0 477E 02D3 3DD5 1430
-uid Siddharth Seth (CODE SIGNING KEY)
-sig 3 3DD51430 2014-03-30 Siddharth Seth (CODE SIGNING KEY)
-sub 4096R/63225E7D 2014-03-30
-sig 3DD51430 2014-03-30 Siddharth Seth (CODE SIGNING KEY)
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
-Comment: GPGTools - http://gpgtools.org
-
-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
-fwn9O0GpWzwQAMot6G4bg9A/
-=a1vb
------END PGP PUBLIC KEY BLOCK-----
-
-BEGIN Key for bikas@apache.org
-pub 4096R/1EFF7770 created: 2014-08-19 expires: never usage: SC
-trust: ultimate validity: ultimate
-sub 4096R/D8797E15 created: 2014-08-19 expires: never usage: E
-[ultimate] (1). Bikas Saha (Code Signing Key)
-N PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v2.0.14 (GNU/Linux)
-
-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
-UtjBC0yAoSJnJL8bVQ8=
-=ATMO
------END PGP PUBLIC KEY BLOCK-----
-END Key for bikas@apache.org
-
-pub 4096R/EF9F98AE 2015-01-05
- Key fingerprint = C2D6 378B BAE4 DE65 BA40 2D3F 7CF6 38AC EF9F 98AE
-uid [ultimate] Jonathan Eagles (CODE SIGNING KEY)
-sig 3 EF9F98AE 2015-01-05 Jonathan Eagles (CODE SIGNING KEY)
-sub 4096R/44223F4F 2015-01-05
-sig EF9F98AE 2015-01-05 Jonathan Eagles (CODE SIGNING KEY)
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v2
-
-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
-7TC3x8qW/hu6bKJINt3Ekcw8nr3e
-=xGxF
------END PGP PUBLIC KEY BLOCK-----
-pub rsa4096/D9B17D1F 2015-05-11
- Key fingerprint = F64E 9745 F021 08C2 9DC5 17A9 090F BE14 D9B1 7D1F
-uid [ultimate] Jeff Zhang (CODE SIGNING KEY)
-sig 3 D9B17D1F 2015-05-11 Jeff Zhang (CODE SIGNING KEY)
-sub rsa4096/66587CE6 2015-05-11
-sig D9B17D1F 2015-05-11 Jeff Zhang (CODE SIGNING KEY)
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v2
-
-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
-/WbM6Bos9jOUGBmt90Qu
-=a3sY
------END PGP PUBLIC KEY BLOCK-----
-pub 4096R/4BC5CC4F 2017-05-31
- Key fingerprint = 5B4C 5D7A 6D53 E269 038F 5A83 9388 FB14 4BC5 CC4F
-uid Zhiyuan Yang (CODE SIGNING KEY)
-sig 3 4BC5CC4F 2017-05-31 Zhiyuan Yang (CODE SIGNING KEY)
-sub 4096R/59CBF136 2017-05-31
-sig 4BC5CC4F 2017-05-31 Zhiyuan Yang (CODE SIGNING KEY)
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1
-
-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
-IRkj5+CIG0OiKX+FQ4e1Tl2RaA==
-=jxBF
------END PGP PUBLIC KEY BLOCK-----
diff --git a/LICENSE.txt b/LICENSE
similarity index 100%
rename from LICENSE.txt
rename to LICENSE
diff --git a/tez-api/src/main/javadoc/resources/META-INF/NOTICE.txt b/NOTICE
similarity index 69%
rename from tez-api/src/main/javadoc/resources/META-INF/NOTICE.txt
rename to NOTICE
index 3f36fcc6ba..2595905699 100644
--- a/tez-api/src/main/javadoc/resources/META-INF/NOTICE.txt
+++ b/NOTICE
@@ -1,5 +1,5 @@
Apache Tez
-Copyright (c) 2016 The Apache Software Foundation
+Copyright 2014-2024 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/Tez_DOAP.rdf b/Tez_DOAP.rdf
index d50e5ab602..257b1e4d82 100644
--- a/Tez_DOAP.rdf
+++ b/Tez_DOAP.rdf
@@ -34,6 +34,55 @@
Java
+
+
+ Version 0.10.4
+ 2024-09-15
+ 0.10.4
+
+
+
+
+ Version 0.10.3
+ 2024-01-31
+ 0.10.3
+
+
+
+
+ Version 0.10.2
+ 2022-07-30
+ 0.10.2
+
+
+
+
+ Version 0.10.1
+ 2021-07-01
+ 0.10.1
+
+
+
+
+ Version 0.10.0
+ 2020-10-15
+ 0.10.0
+
+
+
+
+ Version 0.9.2
+ 2019-03-29
+ 0.9.2
+
+
+
+
+ Version 0.9.1
+ 2018-01-04
+ 0.9.1
+
+ Version 0.9.0
@@ -155,8 +204,8 @@
-
-
+
+
diff --git a/build-tools/.gitignore b/build-tools/.gitignore
new file mode 100644
index 0000000000..adfc42ea48
--- /dev/null
+++ b/build-tools/.gitignore
@@ -0,0 +1,2 @@
+protobuf
+
diff --git a/build-tools/docker/Dockerfile b/build-tools/docker/Dockerfile
new file mode 100644
index 0000000000..5b681067ae
--- /dev/null
+++ b/build-tools/docker/Dockerfile
@@ -0,0 +1,279 @@
+#
+# 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.
+
+###############
+#
+# Apache Yetus Dockerfile for Apache Tez
+# NOTE: This file is compatible with Docker BuildKit. It will work
+# with standard docker build, but it is a lot faster
+# if BuildKit is enabled.
+#
+###############
+
+FROM ubuntu:jammy AS tezbase
+
+WORKDIR /root
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+ENV DEBIAN_FRONTEND noninteractive
+ENV DEBCONF_TERSE true
+
+######
+# Install some basic Apache Yetus requirements
+# some git repos need ssh-client so do it too
+# Adding libffi-dev for all the programming languages
+# that take advantage of it.
+######
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y \
+ apt-transport-https \
+ apt-utils \
+ bzip2 \
+ ca-certificates \
+ curl \
+ dirmngr \
+ git \
+ gpg \
+ gpg-agent \
+ libffi-dev \
+ locales \
+ make \
+ pkg-config \
+ rsync \
+ software-properties-common \
+ ssh-client \
+ xz-utils \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+###
+# Set the locale
+###
+RUN locale-gen en_US.UTF-8
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_ALL en_US.UTF-8
+
+####
+# Install GNU C/C++ (everything generally needs this)
+####
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y \
+ g++ \
+ gcc \
+ libc-dev \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+###
+# Install golang as part of base so we can do each
+# helper utility in parallel. go bins are typically
+# statically linked, so this is perfectly safe.
+###
+# hadolint ignore=DL3008
+RUN add-apt-repository -y ppa:longsleep/golang-backports \
+ && apt-get -q update \
+ && apt-get -q install --no-install-recommends -y golang-go \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+############
+# Fetch all of the non-conflicting bits in parallel
+#############
+
+######
+# Install Google Protobuf 3.21.1
+######
+FROM tezbase AS protobuf
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+RUN mkdir -p /opt/protobuf-src \
+ && curl -L -s -S \
+ https://github.com/protocolbuffers/protobuf/releases/download/v21.1/protobuf-java-3.21.1.tar.gz \
+ -o /opt/protobuf.tar.gz \
+ && tar xzf /opt/protobuf.tar.gz --strip-components 1 -C /opt/protobuf-src
+WORKDIR /opt/protobuf-src
+RUN ./configure --prefix=/opt/protobuf \
+ && make install
+WORKDIR /root
+RUN rm -rf /opt/protobuf-src
+
+####
+# Install shellcheck (shell script lint)
+####
+FROM tezbase AS shellcheck
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+RUN curl -sSL \
+ https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz \
+ | tar --strip-components 1 --wildcards -xJf - '*/shellcheck' \
+ && chmod a+rx shellcheck \
+ && mv shellcheck /bin/shellcheck \
+ && shasum -a 512 /bin/shellcheck \
+ | awk '$1!="aae813283d49f18f95a205dca1c5184267d07534a08abc952ebea1958fee06f8a0207373b6770a083079ba875458ea9da443f2b9910a50dcd93b935048bc14f5" {exit(1)}'
+
+####
+# Install hadolint (dockerfile lint)
+####
+FROM tezbase AS hadolint
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+RUN curl -sSL \
+ https://github.com/hadolint/hadolint/releases/download/v1.18.0/hadolint-Linux-x86_64 \
+ -o /bin/hadolint \
+ && chmod a+rx /bin/hadolint \
+ && shasum -a 512 /bin/hadolint \
+ | awk '$1!="df27253d374c143a606483b07a26234ac7b4bca40b4eba53e79609c81aa70146e7d5c145f90dcec71d6d1aad1048b7d9d2de68d92284f48a735d04d19c5c5559" {exit(1)}'
+
+####
+# Install buf (protobuf lint)
+####
+FROM tezbase AS buf
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+RUN curl -sSL \
+ https://github.com/bufbuild/buf/releases/download/v0.21.0/buf-Linux-x86_64.tar.gz \
+ -o buf.tar.gz \
+ && shasum -a 256 buf.tar.gz \
+ | awk '$1!="95aba62ac0ecc5a9120cc58c65cdcc85038633a816bddfe8398c5ae3b32803f1" {exit(1)}' \
+ && tar -xzf buf.tar.gz -C /usr/local --strip-components 1 \
+ && rm buf.tar.gz
+
+########
+#
+#
+# Content that needs to be installed in order due to packages...
+#
+#
+########
+
+FROM tezbase
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+####
+# Install java (first, since we want to dicate what form of Java)
+####
+
+####
+# OpenJDK 8
+####
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y openjdk-8-jdk-headless \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+####
+# OpenJDK 11 (but keeps default to JDK8)
+# NOTE: This default only works when Apache Yetus is launched
+# _in_ the container and not outside of it!
+####
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y default-jre-headless openjdk-11-jdk-headless \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+ && update-java-alternatives -s java-1.8.0-openjdk-amd64 || :
+# since update alternatives might fail on executables that we don't really need (e.g. appletviewer)
+# and return with exit code <0 (actually: 2), we can simply do a sanity check if the version is
+# as expected for "java" executable after the update and go on
+RUN java -version 2>&1 | grep "1.8.0" && rm -f /usr/lib/jvm/default-java \
+ && ln -s java-8-openjdk-amd64 /usr/lib/jvm/default-java
+ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
+
+######
+# Install findbugs
+######
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y findbugs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+ENV FINDBUGS_HOME /usr
+
+######
+# Install maven
+######
+# hadolint ignore=DL3008
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y maven \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+######
+# Install python3 and pylint3
+# astroid and pylint go hand-in-hand. Upgrade both at the same time.
+######
+# hadolint ignore=DL3008,DL3013
+RUN apt-get -q update && apt-get -q install --no-install-recommends -y \
+ python3 \
+ python3-bcrypt \
+ python3-cffi \
+ python3-cryptography \
+ python3-dateutil \
+ python3-dev \
+ python3-dev \
+ python3-isort \
+ python3-dockerpty \
+ python3-nacl \
+ python3-pyrsistent \
+ python3-setuptools \
+ python3-setuptools \
+ python3-singledispatch \
+ python3-six \
+ python3-wheel \
+ python3-wrapt \
+ python3-yaml \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+ && curl -sSL https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py \
+ && python3 /tmp/get-pip.py \
+ && rm /usr/local/bin/pip /tmp/get-pip.py \
+ && pip3 install -v \
+ astroid==2.4.2 \
+ codespell==2.0 \
+ pylint==2.5.3 \
+ yamllint==1.24.2 \
+ && rm -rf /root/.cache \
+ && mv /usr/local/bin/pylint /usr/local/bin/pylint3
+RUN ln -s /usr/local/bin/pylint3 /usr/local/bin/pylint
+RUN ln -s /usr/local/bin/pip3 /usr/local/bin/pip
+
+###
+# Install npm and JSHint
+###
+# hadolint ignore=DL3008
+RUN curl -sSL https://deb.nodesource.com/setup_14.x | bash - \
+ && apt-get -q install --no-install-recommends -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+ && npm install -g \
+ jshint@2.12.0 \
+ markdownlint-cli@0.23.2 \
+ && rm -rf /root/.npm
+
+#####
+# Now all the stuff that was built in parallel
+#####
+
+COPY --from=shellcheck /bin/shellcheck /bin/shellcheck
+COPY --from=hadolint /bin/hadolint /bin/hadolint
+COPY --from=buf /usr/local/bin/buf /usr/local/bin/buf
+COPY --from=protobuf /opt/protobuf /opt/protobuf
+
+ENV PROTOBUF_HOME /opt/protobuf
+ENV PROTOC_PATH /opt/protobuf/bin/protoc
+ENV PATH "${PATH}:/opt/protobuf/bin"
+
+####
+# YETUS CUT HERE
+# Magic text above! Everything from here on is ignored
+# by Yetus, so could include anything not needed
+# by your testing environment
+###
diff --git a/build-tools/test-patch.sh b/build-tools/test-patch.sh
index e1fa0fb00d..9b457af221 100755
--- a/build-tools/test-patch.sh
+++ b/build-tools/test-patch.sh
@@ -38,6 +38,8 @@ GREP=${GREP:-grep}
PATCH=${PATCH:-patch}
DIFF=${DIFF:-diff}
JIRACLI=${JIRA:-jira}
+SED=${SED:-sed}
+CURL=${CURL:-curl}
FINDBUGS_HOME=${FINDBUGS_HOME}
###############################################################################
@@ -702,10 +704,24 @@ $comment"
echo "======================================================================"
echo ""
echo ""
+
+ # RESTify the comment
+ jsoncomment=$(echo "$comment" \
+ | ${SED} -e 's,\\,\\\\,g' \
+ -e 's,\",\\\",g' \
+ -e 's,$,\\r\\n,g' \
+ | tr -d '\n')
+ jsoncomment='{"body":"'"$jsoncomment"'"}'
+
### Update Jira with a comment
- export USER=hudson
- $JIRACLI -s https://issues.apache.org/jira -a addcomment -u tezqa -p $JIRA_PASSWD --comment "$comment" --issue $defect
- $JIRACLI -s https://issues.apache.org/jira -a logout -u tezqa -p $JIRA_PASSWD
+ ${CURL} -X POST \
+ -H "Accept: application/json" \
+ -H "Content-Type: application/json" \
+ -u "tezqa:${JIRA_PASSWD}" \
+ -d "$jsoncomment" \
+ --silent --location \
+ "https://issues.apache.org/jira/rest/api/2/issue/${defect}/comment" \
+ >/dev/null
fi
}
diff --git a/docs/pom.xml b/docs/pom.xml
index 472975d04d..9517e45770 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -21,13 +21,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
TezTez is an application framework which allows for a complex directed-acyclic-graph of tasks for processing data and is built atop Apache Hadoop YARN.
- http://tez.apache.org/
+ https://tez.apache.org/4.0.0org.apache.teztez
- 0.9.1-SNAPSHOT
+ 0.10.5-SNAPSHOTtez-docspom
@@ -35,14 +35,14 @@
Apache 2
- http://www.apache.org/licenses/LICENSE-2.0.txt
+ https://www.apache.org/licenses/LICENSE-2.0.txtrepoJira
- http://issues.apache.org/jira/browse/TEZ
+ https://issues.apache.org/jira/browse/TEZ
@@ -53,7 +53,7 @@
mailto:user-unsubscribe@tez.apache.org
mailto:user@tez.apache.org
- http://mail-archives.apache.org/mod_mbox/tez-user/
+ https://mail-archives.apache.org/mod_mbox/tez-user/Development list
@@ -62,7 +62,7 @@
mailto:dev-unsubscribe@tez.apache.org
mailto:dev@tez.apache.org
- http://mail-archives.apache.org/mod_mbox/tez-dev/
+ https://mail-archives.apache.org/mod_mbox/tez-dev/Commit list
@@ -71,7 +71,7 @@
mailto:commits-unsubscribe@tez.apache.org
mailto:commits@tez.apache.org
- http://mail-archives.apache.org/mod_mbox/tez-commits/
+ https://mail-archives.apache.org/mod_mbox/tez-commits/JIRA Issues list
@@ -80,7 +80,7 @@
mailto:issues-unsubscribe@tez.apache.org
mailto:issues@tez.apache.org
- http://mail-archives.apache.org/mod_mbox/tez-issues/
+ https://mail-archives.apache.org/mod_mbox/tez-issues/
@@ -238,6 +238,15 @@
PMC
+
+ abstractdog
+ Laszlo Bodor
+ abstractdog@apache.org
+ +1
+
+ Committer
+
+ kamrulMohammad Kamrul Islam
@@ -431,7 +440,7 @@
Apache Software Foundation
- http://www.apache.org/
+ https://www.apache.org/
@@ -458,6 +467,7 @@
org.apache.maven.pluginsmaven-site-plugin
+ ${maven-site-plugin.version}./target
@@ -478,6 +488,7 @@
org.apache.maven.pluginsmaven-project-info-reports-plugin
+ ${maven-project-info-reports-plugin.version}${project.basedir}/src/site/custom/project-info-report.propertiesfalse
@@ -485,10 +496,10 @@
- project-team
- mailing-list
- issue-tracking
- license
+ team
+ mailing-lists
+ issue-management
+ licenses
diff --git a/docs/src/site/markdown/by-laws.md b/docs/src/site/markdown/by-laws.md
index 28ecabb852..4ea47d544b 100644
--- a/docs/src/site/markdown/by-laws.md
+++ b/docs/src/site/markdown/by-laws.md
@@ -42,7 +42,8 @@ All of the volunteers who are contributing time, code, documentation, or resourc
The project's Committers are responsible for the project's technical management. All committers have write access to the project's source repositories. Committers may cast binding votes on any technical discussion regarding the project.
-Committer access is by invitation only and must be approved by lazy consensus of the active PMC members. A Committer may request removal of their commit privileges by their own declaration. A committer will be considered "emeritus/inactive" by not contributing in any form to the project for over 1 year. An emeritus committer may request reinstatement of commit access from the PMC. Such reinstatement is subject to lazy consensus of active PMC members.
+
+Committer access is by invitation only and must be approved by lazy consensus of the active PMC members. A Committer may request removal of their commit privileges by their own declaration.
Commit access can be revoked by a unanimous vote of all the active PMC members (except the committer in question if they are also a PMC member).
@@ -61,7 +62,7 @@ The Project Management Committee (PMC) for Apache Tez was created by a resolutio
- Nominating new PMC members and committers
- Maintaining these bylaws and other guidelines of the project
-Membership of the PMC is by invitation only and must be approved by a lazy consensus of active PMC members. A PMC member is considered "emeritus/inactive" by not contributing in any form to the project for over one year. An emeritus PMC member may request reinstatement to the PMC. Such reinstatement is subject to lazy consensus of active PMC members. A PMC member may resign their membership from the PMC by their own declaration. Membership of the PMC can be revoked by an unanimous vote of all the active PMC members other than the member in question.
+Membership of the PMC is by invitation only and must be approved by a lazy consensus of active PMC members. A PMC member may resign their membership from the PMC by their own declaration. Membership of the PMC can also be revoked via a Board resolution.
The chair of the PMC is appointed by the ASF board. The chair is an office holder of the Apache Software Foundation (Vice President, Apache Tez) and has primary responsibility to the board for the management of the projects within the scope of the Tez PMC. The chair reports to the board quarterly on developments within the Tez project. The PMC may consider the position of PMC chair annually, and if supported by a successful vote to change the PMC chair, may recommend a new chair to the board. Ultimately, however, it is the board's responsibility who it chooses to appoint as the PMC chair.
@@ -123,9 +124,9 @@ This section describes the various actions which are undertaken within the proje
Votes are open for a period of a minimum of 3 days (excluding weekend days) to allow all active voters time to consider the vote. For any votes requiring full consensus or a 2/3 majority, the vote should remain open for a minimum of 1 week. Votes relating to code changes are not subject to a strict timetable but should be made as timely as possible.
-[Apache Software Foundation]: http://www.apache.org/foundation/
-[Incubator project]: http://incubator.apache.org/
-[Foundation FAQ]: http://www.apache.org/foundation/faq.html
-[Committer FAQ]: http://www.apache.org/dev/committers.html
-[CLA]: http://www.apache.org/licenses/icla.txt
-[set of roles]: http://www.apache.org/foundation/how-it-works.html#roles
+[Apache Software Foundation]: https://www.apache.org/foundation/
+[Incubator project]: https://incubator.apache.org/
+[Foundation FAQ]: https://www.apache.org/foundation/faq.html
+[Committer FAQ]: https://www.apache.org/dev/committers.html
+[CLA]: https://www.apache.org/licenses/icla.txt
+[set of roles]: https://www.apache.org/foundation/how-it-works.html#roles
diff --git a/docs/src/site/markdown/index.md b/docs/src/site/markdown/index.md
index d0f307a4b4..fc47f533a1 100644
--- a/docs/src/site/markdown/index.md
+++ b/docs/src/site/markdown/index.md
@@ -15,15 +15,15 @@
limitations under the License.
-->
-Welcome to Apache Tez™
+Welcome to Apache TEZ®
Introduction
------------
-The Apache Tez™ project is aimed at building an application framework
+The Apache TEZ® project is aimed at building an application framework
which allows for a complex directed-acyclic-graph of tasks for processing
data. It is currently built atop
-[Apache Hadoop YARN](http://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html).
+[Apache Hadoop YARN](https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/YARN.html).
The 2 main design themes for Tez are:
diff --git a/docs/src/site/markdown/install.md b/docs/src/site/markdown/install.md
index b1cdcf9583..44ca862a82 100644
--- a/docs/src/site/markdown/install.md
+++ b/docs/src/site/markdown/install.md
@@ -34,11 +34,11 @@ or higher.
2. Build tez using `mvn clean package -DskipTests=true -Dmaven.javadoc.skip=true`
- This assumes that you have already installed JDK8 or later and Maven 3 or later.
- - Tez also requires Protocol Buffers 2.5.0, including the protoc-compiler.
+ - Tez also requires Protocol Buffers 3.19.4, including the protoc-compiler.
* This can be downloaded from https://github.com/google/protobuf/tags/.
* On Mac OS X with the homebrew package manager `brew install protobuf250`
- * For rpm-based linux systems, the yum repos may not have the 2.5.0 version.
- `rpm.pbone.net` has the protobuf-2.5.0 and protobuf-compiler-2.5.0 packages.
+ * For rpm-based linux systems, the yum repos may not have the 3.19.4 version.
+ `rpm.pbone.net` has the protobuf-3.19.4 and protobuf-compiler-3.19.4 packages.
- If you prefer to run the unit tests, remove skipTests from the
command above.
- If you use Eclipse IDE, you can import the projects using
diff --git a/docs/src/site/markdown/install_pre_0_5_0.md b/docs/src/site/markdown/install_pre_0_5_0.md
index 494ff54270..5123c14014 100644
--- a/docs/src/site/markdown/install_pre_0_5_0.md
+++ b/docs/src/site/markdown/install_pre_0_5_0.md
@@ -20,7 +20,7 @@
[Install instructions for Tez (post 0.5.0)](./install.html)
-----------------------------------------------------------------------------------
-Install/Deploy Instructions for Tez release pre-0.5.0 E.g. [(Tez-0.4.1)](http://archive.apache.org/dist/incubator/tez/tez-0.4.1-incubating/)
+Install/Deploy Instructions for Tez release pre-0.5.0 E.g. [(Tez-0.4.1)](https://archive.apache.org/dist/incubator/tez/tez-0.4.1-incubating/)
--------------------------------------------------------------------------------------------------------------------------------------------------
1. Deploy Apache Hadoop using either the 2.2.0 release or a compatible
diff --git a/docs/src/site/markdown/privacy-policy.md b/docs/src/site/markdown/privacy-policy.md
deleted file mode 100644
index 95825d0604..0000000000
--- a/docs/src/site/markdown/privacy-policy.md
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-Privacy Policy
-
-Privacy Policy
---------------
-
-Information about your use of this website is collected using server
-access logs and a tracking cookie. The collected information consists of
-the following:
-
-1. The IP address from which you access the website;
-
-2. The type of browser and operating system you use to access our site;
-
-3. The date and time you access our site;
-
-4. The pages you visit; and
-
-5. The addresses of pages from where you followed a link to our site.
-
-Part of this information is gathered using a tracking cookie set by the
-[Google Analytics](http://www.google.com/analytics/) service and handled
-by Google as described in their [privacy
-policy](http://www.google.com/privacy.html). See your browser
-documentation for instructions on how to disable the cookie if you
-prefer not to share this data with Google.
-
-We use the gathered information to help us make our site more useful to
-visitors and to better understand how and when our site is used. We do
-not track or collect personally identifiable information or associate
-gathered data with any personally identifying information from other
-sources.
-
-By using this website, you consent to the collection of this data in the
-manner and for the purpose described above.
-
diff --git a/docs/src/site/markdown/releases/apache-tez-0-10-0.md b/docs/src/site/markdown/releases/apache-tez-0-10-0.md
new file mode 100644
index 0000000000..0ba6f7e243
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-10-0.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.10.0
+
+Apache TEZ® 0.10.0
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.10.0/)
+- [Release Notes](0.10.0/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.10.0/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.10.0/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.10.0/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.10.0/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.10.0/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-10-1.md b/docs/src/site/markdown/releases/apache-tez-0-10-1.md
new file mode 100644
index 0000000000..efe346aae0
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-10-1.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.10.1
+
+Apache TEZ® 0.10.1
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.10.1/)
+- [Release Notes](0.10.1/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.10.1/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.10.1/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.10.1/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.10.1/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.10.1/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-10-2.md b/docs/src/site/markdown/releases/apache-tez-0-10-2.md
new file mode 100644
index 0000000000..2e3cc49c26
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-10-2.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.10.2
+
+Apache TEZ® 0.10.2
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.10.2/)
+- [Release Notes](0.10.2/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.10.2/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.10.2/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.10.2/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.10.2/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.10.2/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-10-3.md b/docs/src/site/markdown/releases/apache-tez-0-10-3.md
new file mode 100644
index 0000000000..3e86896861
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-10-3.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.10.3
+
+Apache TEZ® 0.10.3
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.10.3/)
+- [Release Notes](0.10.3/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.10.3/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.10.3/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.10.3/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.10.3/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.10.3/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-10-4.md b/docs/src/site/markdown/releases/apache-tez-0-10-4.md
new file mode 100644
index 0000000000..7028172664
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-10-4.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.10.4
+
+Apache TEZ® 0.10.4
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.10.4/)
+- [Release Notes](0.10.4/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.10.4/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.10.4/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.10.4/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.10.4/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.10.4/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-5-0.md b/docs/src/site/markdown/releases/apache-tez-0-5-0.md
index f206ea6f7f..c8cd2e696f 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-5-0.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-5-0.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.5.0
+Apache TEZ® 0.5.0
-Apache Tez™ 0.5.0
+Apache TEZ® 0.5.0
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.5.0/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-5-1.md b/docs/src/site/markdown/releases/apache-tez-0-5-1.md
index 01417ba347..12c3c001ab 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-5-1.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-5-1.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.5.1
+Apache TEZ® 0.5.1
-Apache Tez™ 0.5.1
+Apache TEZ® 0.5.1
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.5.1/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-5-2.md b/docs/src/site/markdown/releases/apache-tez-0-5-2.md
index 99ca44b759..6acb130e47 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-5-2.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-5-2.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.5.2
+Apache TEZ® 0.5.2
-Apache Tez™ 0.5.2
+Apache TEZ® 0.5.2
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.5.2/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-5-3.md b/docs/src/site/markdown/releases/apache-tez-0-5-3.md
index 7e00fe9092..750fe30536 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-5-3.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-5-3.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.5.3
+Apache TEZ® 0.5.3
-Apache Tez™ 0.5.3
+Apache TEZ® 0.5.3
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.5.3/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-5-4.md b/docs/src/site/markdown/releases/apache-tez-0-5-4.md
index 9d3f96c03b..54c5d0501d 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-5-4.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-5-4.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.5.4
+Apache TEZ® 0.5.4
-Apache Tez™ 0.5.4
+Apache TEZ® 0.5.4
----------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.5.4/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-6-0.md b/docs/src/site/markdown/releases/apache-tez-0-6-0.md
index 473d03b807..96048bcb28 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-6-0.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-6-0.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.6.0
+Apache TEZ® 0.6.0
-Apache Tez™ 0.6.0
+Apache TEZ® 0.6.0
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.6.0/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-6-1.md b/docs/src/site/markdown/releases/apache-tez-0-6-1.md
index 12854778b2..17b7d647e5 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-6-1.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-6-1.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.6.1
+Apache TEZ® 0.6.1
-Apache Tez™ 0.6.1
+Apache TEZ® 0.6.1
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/tez/0.6.1/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-6-2.md b/docs/src/site/markdown/releases/apache-tez-0-6-2.md
index 5a898e6c96..b1f97572b2 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-6-2.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-6-2.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.6.2
+Apache TEZ® 0.6.2
-Apache Tez™ 0.6.2
+Apache TEZ® 0.6.2
----------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.6.2/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-7-0.md b/docs/src/site/markdown/releases/apache-tez-0-7-0.md
index 8c0f956c60..fd8b48d646 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-7-0.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-7-0.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.7.0
+Apache TEZ® 0.7.0
-Apache Tez™ 0.7.0
+Apache TEZ® 0.7.0
----------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.7.0/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-7-1.md b/docs/src/site/markdown/releases/apache-tez-0-7-1.md
index 1c1766f241..152bd47053 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-7-1.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-7-1.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.7.1
+Apache TEZ® 0.7.1
-Apache Tez™ 0.7.1
+Apache TEZ® 0.7.1
----------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.7.1/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-0-alpha.md b/docs/src/site/markdown/releases/apache-tez-0-8-0-alpha.md
index 5854ecd74f..2a1d4d18ec 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-0-alpha.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-0-alpha.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.0-alpha
+Apache TEZ® 0.8.0-alpha
-Apache Tez™ 0.8.0-alpha
+Apache TEZ® 0.8.0-alpha
----------------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.8.0-alpha/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-1-alpha.md b/docs/src/site/markdown/releases/apache-tez-0-8-1-alpha.md
index 806292beb9..c8db8ed56b 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-1-alpha.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-1-alpha.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.1-alpha
+Apache TEZ® 0.8.1-alpha
-Apache Tez™ 0.8.1-alpha
+Apache TEZ® 0.8.1-alpha
----------------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.8.1-alpha/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-2.md b/docs/src/site/markdown/releases/apache-tez-0-8-2.md
index 8c25155323..f7282ff1b6 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-2.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-2.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.2
+Apache TEZ® 0.8.2
-Apache Tez™ 0.8.2
+Apache TEZ® 0.8.2
----------------------
- [Download Release Artifacts](http://archive.apache.org/dist/tez/0.8.2/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-3.md b/docs/src/site/markdown/releases/apache-tez-0-8-3.md
index 5318652b6f..ca871779ba 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-3.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-3.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.3
+Apache TEZ® 0.8.3
-Apache Tez™ 0.8.3
+Apache TEZ® 0.8.3
----------------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.8.3/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-4.md b/docs/src/site/markdown/releases/apache-tez-0-8-4.md
index 2250dbee4c..802db939ab 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-4.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-4.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.4
+Apache TEZ® 0.8.4
-Apache Tez™ 0.8.4
+Apache TEZ® 0.8.4
----------------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.8.4/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-8-5.md b/docs/src/site/markdown/releases/apache-tez-0-8-5.md
index 9b73cec00a..cebc17a405 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-8-5.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-8-5.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.8.5
+Apache TEZ® 0.8.5
-Apache Tez™ 0.8.5
+Apache TEZ® 0.8.5
----------------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.8.5/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-9-0.md b/docs/src/site/markdown/releases/apache-tez-0-9-0.md
index 5059790dd8..12095ac2b6 100644
--- a/docs/src/site/markdown/releases/apache-tez-0-9-0.md
+++ b/docs/src/site/markdown/releases/apache-tez-0-9-0.md
@@ -15,9 +15,9 @@
limitations under the License.
-->
-Apache Tez™ 0.9.0
+Apache TEZ® 0.9.0
-Apache Tez™ 0.9.0
+Apache TEZ® 0.9.0
----------------------
- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.9.0/)
diff --git a/docs/src/site/markdown/releases/apache-tez-0-9-1.md b/docs/src/site/markdown/releases/apache-tez-0-9-1.md
new file mode 100644
index 0000000000..452bce5f5d
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-9-1.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.9.1
+
+Apache TEZ® 0.9.1
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.9.1/)
+- [Release Notes](0.9.1/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.9.1/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.9.1/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.9.1/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.9.1/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.9.1/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/apache-tez-0-9-2.md b/docs/src/site/markdown/releases/apache-tez-0-9-2.md
new file mode 100644
index 0000000000..d29cd6d4e0
--- /dev/null
+++ b/docs/src/site/markdown/releases/apache-tez-0-9-2.md
@@ -0,0 +1,30 @@
+
+
+Apache TEZ® 0.9.2
+
+Apache TEZ® 0.9.2
+----------------------
+
+- [Download Release Artifacts](http://www.apache.org/dyn/closer.lua/tez/0.9.2/)
+- [Release Notes](0.9.2/release-notes.txt)
+- Documentation
+ - [API Javadocs](0.9.2/tez-api-javadocs/index.html) : Documentation for the Tez APIs
+ - [Runtime Library Javadocs](0.9.2/tez-runtime-library-javadocs/index.html) : Documentation for built-in implementations of useful Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Mapreduce Javadocs](0.9.2/tez-mapreduce-javadocs/index.html) : Documentation for built-in implementations of Mapreduce compatible Inputs, Outputs, Processors etc. written based on the Tez APIs
+ - [Tez Configuration](0.9.2/tez-api-javadocs/configs/TezConfiguration.html) : Documentation for configurations of Tez. These configurations are typically specified in tez-site.xml.
+ - [Tez Runtime Configuration](0.9.2/tez-runtime-library-javadocs/configs/TezRuntimeConfiguration.html) : Documentation for runtime configurations of Tez. These configurations are typically specified by job submitters.
diff --git a/docs/src/site/markdown/releases/index.md b/docs/src/site/markdown/releases/index.md
index 9e9df225ff..9be6f8bf12 100644
--- a/docs/src/site/markdown/releases/index.md
+++ b/docs/src/site/markdown/releases/index.md
@@ -15,24 +15,31 @@
limitations under the License.
-->
-Apache Tez™ Releases
+Apache TEZ® Releases
Releases
------------
-- [Apache Tez™ 0.9.0](./apache-tez-0-9-0.html) (Jul 27, 2017)
-- [Apache Tez™ 0.8.5](./apache-tez-0-8-5.html) (Mar 13, 2017)
-- [Apache Tez™ 0.8.4](./apache-tez-0-8-4.html) (Jul 08, 2016)
-- [Apache Tez™ 0.8.3](./apache-tez-0-8-3.html) (Apr 15, 2016)
-- [Apache Tez™ 0.8.2](./apache-tez-0-8-2.html) (Jan 19, 2016)
-- [Apache Tez™ 0.8.1-alpha](./apache-tez-0-8-1-alpha.html) (Oct 12, 2015)
-- [Apache Tez™ 0.8.0-alpha](./apache-tez-0-8-0-alpha.html) (Sep 01, 2015)
-- [Apache Tez™ 0.7.1](./apache-tez-0-7-1.html) (May 10, 2016)
-- [Apache Tez™ 0.7.0](./apache-tez-0-7-0.html) (May 18, 2015)
-- [Apache Tez™ 0.6.2](./apache-tez-0-6-2.html) (Aug 07, 2015)
-- [Apache Tez™ 0.6.1](./apache-tez-0-6-1.html) (May 18, 2015)
-- [Apache Tez™ 0.6.0](./apache-tez-0-6-0.html) (Jan 23, 2015)
-- [Apache Tez™ 0.5.4](./apache-tez-0-5-4.html) (Jun 26, 2015)
-- [Apache Tez™ 0.5.3](./apache-tez-0-5-3.html) (Dec 10, 2014)
-- [Apache Tez™ 0.5.2](./apache-tez-0-5-2.html) (Nov 07, 2014)
-- [Apache Tez™ 0.5.1](./apache-tez-0-5-1.html) (Oct 08, 2014)
-- [Apache Tez™ 0.5.0](./apache-tez-0-5-0.html) (Sep 04, 2014)
+- [Apache TEZ® 0.10.4](./apache-tez-0-10-4.html) (Sep 15, 2024)
+- [Apache TEZ® 0.10.3](./apache-tez-0-10-3.html) (Jan 31, 2024)
+- [Apache TEZ® 0.10.2](./apache-tez-0-10-2.html) (Jul 30, 2022)
+- [Apache TEZ® 0.10.1](./apache-tez-0-10-1.html) (Jul 01, 2021)
+- [Apache TEZ® 0.10.0](./apache-tez-0-10-0.html) (Oct 15, 2020)
+- [Apache TEZ® 0.9.2](./apache-tez-0-9-2.html) (Mar 29, 2019)
+- [Apache TEZ® 0.9.1](./apache-tez-0-9-1.html) (Jan 04, 2018)
+- [Apache TEZ® 0.9.0](./apache-tez-0-9-0.html) (Jul 27, 2017)
+- [Apache TEZ® 0.8.5](./apache-tez-0-8-5.html) (Mar 13, 2017)
+- [Apache TEZ® 0.8.4](./apache-tez-0-8-4.html) (Jul 08, 2016)
+- [Apache TEZ® 0.8.3](./apache-tez-0-8-3.html) (Apr 15, 2016)
+- [Apache TEZ® 0.8.2](./apache-tez-0-8-2.html) (Jan 19, 2016)
+- [Apache TEZ® 0.8.1-alpha](./apache-tez-0-8-1-alpha.html) (Oct 12, 2015)
+- [Apache TEZ® 0.8.0-alpha](./apache-tez-0-8-0-alpha.html) (Sep 01, 2015)
+- [Apache TEZ® 0.7.1](./apache-tez-0-7-1.html) (May 10, 2016)
+- [Apache TEZ® 0.7.0](./apache-tez-0-7-0.html) (May 18, 2015)
+- [Apache TEZ® 0.6.2](./apache-tez-0-6-2.html) (Aug 07, 2015)
+- [Apache TEZ® 0.6.1](./apache-tez-0-6-1.html) (May 18, 2015)
+- [Apache TEZ® 0.6.0](./apache-tez-0-6-0.html) (Jan 23, 2015)
+- [Apache TEZ® 0.5.4](./apache-tez-0-5-4.html) (Jun 26, 2015)
+- [Apache TEZ® 0.5.3](./apache-tez-0-5-3.html) (Dec 10, 2014)
+- [Apache TEZ® 0.5.2](./apache-tez-0-5-2.html) (Nov 07, 2014)
+- [Apache TEZ® 0.5.1](./apache-tez-0-5-1.html) (Oct 08, 2014)
+- [Apache TEZ® 0.5.0](./apache-tez-0-5-0.html) (Sep 04, 2014)
diff --git a/docs/src/site/markdown/talks.md b/docs/src/site/markdown/talks.md
index a29d553dfc..fe017bd048 100644
--- a/docs/src/site/markdown/talks.md
+++ b/docs/src/site/markdown/talks.md
@@ -21,12 +21,5 @@ Talks
-----
- Apache Tez : Accelerating Hadoop Query Processing by Bikas Saha and
Hitesh Shah at [Hadoop Summit 2014, San Jose, CA, USA](http://hadoopsummit.org/san-jose/)
- - [Slides](http://www.slideshare.net/Hadoop_Summit/w-1205phall1saha)
- - [Video](http://www.youtube.com/watch?v=yf_hBiZy3nk)
-
-User Meetup Recordings
-----------------------
-
-- [Recording](https://hortonworks.webex.com/hortonworks/ldr.php?AT=pb&SP=MC&rID=125516477&rKey=d147a3c924b64496)
- from [Meetup on July 31st, 2013](http://www.meetup.com/Apache-Tez-User-Group/events/130852782/)
- at [Hortonworks Inc](http://hortonworks.com)
+ - [Slides](https://www.slideshare.net/Hadoop_Summit/w-1205phall1saha)
+ - [Video](https://www.youtube.com/watch?v=yf_hBiZy3nk)
diff --git a/docs/src/site/markdown/tez-ui.md b/docs/src/site/markdown/tez-ui.md
index 3855fbbb97..423018fdf5 100644
--- a/docs/src/site/markdown/tez-ui.md
+++ b/docs/src/site/markdown/tez-ui.md
@@ -128,7 +128,7 @@ yarn-site.xml
...
```
-__For more detailed information (setup, configuration, deployment), please refer to the [Apache Hadoop Documentation on the Application Timeline Server](http://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/TimelineServer.html)__
+__For more detailed information (setup, configuration, deployment), please refer to the [Apache Hadoop Documentation on the Application Timeline Server](https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/TimelineServer.html)__
__For general information on the compatibility matrix of the Tez UI with YARN TimelineServer, please refer to the [Tez - Timeline Server Guide](tez_yarn_timeline.html)__
diff --git a/docs/src/site/markdown/tez_acls.md b/docs/src/site/markdown/tez_acls.md
index 52d9661b32..8a488e00c0 100644
--- a/docs/src/site/markdown/tez_acls.md
+++ b/docs/src/site/markdown/tez_acls.md
@@ -21,16 +21,16 @@
Access control in Tez can be categorized as follows:
- - Modify permissions on the Tez AM ( or Session ). Users with this permision can:
+ - Modify permissions on the Tez AM ( or Session ). Users with this permission can:
- Submit a DAG to a Tez Session
- Kill any DAG within the given AM/Session
- Kill the Session
- - View permissions on the Tez AM ( or Session ). Users with this permision can:
+ - View permissions on the Tez AM ( or Session ). Users with this permission can:
- Monitor/View the status of the Session
- Monitor/View the progress/status of any DAG within the given AM/Session
- - Modify permissions on a particular Tez DAG. Users with this permision can:
+ - Modify permissions on a particular Tez DAG. Users with this permission can:
- Kill the DAG
- - View permissions on a particular Tez DAG. Users with this permision can:
+ - View permissions on a particular Tez DAG. Users with this permission can:
- Monitor/View the progress/status of the DAG
From the above, you can see that All users/groups that have access to do operations on the AM also have access to similar operations on all DAGs within that AM/session. Also, by default, the owner of the Tez AM, i.e. the user who started the Tez AM, is considered a super-user and has access to all operations on the AM as well as all DAGs within the AM/Session.
diff --git a/docs/src/site/markdown/tez_yarn_timeline.md b/docs/src/site/markdown/tez_yarn_timeline.md
index 745f65c044..cbe28b4966 100644
--- a/docs/src/site/markdown/tez_yarn_timeline.md
+++ b/docs/src/site/markdown/tez_yarn_timeline.md
@@ -18,7 +18,7 @@
## YARN Timeline Background
-Initial support for [YARN Timeline](http://hadoop.apache.org/docs/r2.4.0/hadoop-yarn/hadoop-yarn-site/TimelineServer.html) was introduced in Apache Hadoop 2.4.0. Support for ACLs in Timeline was introduced in Apache Hadoop 2.6.0. Support for Timeline was introduced in Tez in 0.5.x ( with some experimental support in 0.4.x ). However, Tez ACLs integration with Timeline is only available from Tez 0.6.0 onwards.
+Initial support for [YARN Timeline](https://hadoop.apache.org/docs/r2.4.0/hadoop-yarn/hadoop-yarn-site/TimelineServer.html) was introduced in Apache Hadoop 2.4.0. Support for ACLs in Timeline was introduced in Apache Hadoop 2.6.0. Support for Timeline was introduced in Tez in 0.5.x ( with some experimental support in 0.4.x ). However, Tez ACLs integration with Timeline is only available from Tez 0.6.0 onwards.
## How Tez Uses YARN Timeline
diff --git a/docs/src/site/site.xml b/docs/src/site/site.xml
index 91d15a911f..b69602f561 100644
--- a/docs/src/site/site.xml
+++ b/docs/src/site/site.xml
@@ -22,7 +22,7 @@
org.apache.maven.skinsmaven-fluido-skin
- 1.3.0
+ 1.9
@@ -42,13 +42,13 @@
./images/ApacheTezLogo_lowres.png25%25%
- http://tez.apache.org/
+ https://tez.apache.org/Apache Software Foundation
- http://www.apache.org/images/asf_logo.gif
- http://www.apache.org/
+ https://apache.org/foundation/press/kit/asf_logo_wide.png
+ https://www.apache.org/
@@ -56,24 +56,23 @@
-
-
+ ]]>
-
+
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.2.1
- org.apache.maven.pluginsmaven-javadoc-plugin
- ${javadoc-maven-plugin.version}
- -Xdoclint:none
+ none
@@ -818,11 +875,6 @@
hadoop-maven-plugins${hadoop.version}
-
- org.apache.maven.plugins
- maven-assembly-plugin
- 2.4
- com.github.eirslettfrontend-maven-plugin
@@ -831,22 +883,11 @@
exec-maven-pluginorg.codehaus.mojo
- 1.3.2
-
-
- org.apache.maven.plugins
- maven-war-plugin
- 2.5
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- ${shade-maven-plugin.version}
+ ${codehaus.mojo.version}org.apache.ratapache-rat-plugin
- 0.10CHANGES.txt
@@ -873,10 +914,14 @@
+
+ com.github.os72
+ protoc-jar-maven-plugin
+ ${protoc-jar-maven-plugin.version}
+ org.apache.maven.pluginsmaven-surefire-plugin
- 2.14.11false
@@ -887,43 +932,52 @@
4
+ ${test.build.data}true${hadoop.version}
-
- org.codehaus.mojo
- findbugs-maven-plugin
- ${findbugs-maven-plugin.version}
- org.apache.maven.plugins
- maven-resources-plugin
- 2.6
+ maven-checkstyle-plugin
+ ${maven-checkstyle-plugin.version}
+
+
+ org.apache.tez
+ tez-build-tools
+ ${project.version}
+
+
+ com.puppycrawl.tools
+ checkstyle
+ ${checkstyle.version}
+
+
- UTF-8
+ checkstyle/checkstyle.xml
+ checkstyle/suppressions.xml
+ true
+ false
+ xml
+ html
+ ${project.build.directory}/test/checkstyle-errors.xml
- org.apache.maven.plugins
- maven-site-plugin
- 3.4
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
- 2.8.1
+ org.owasp
+ dependency-check-maven
+ ${dependency-check-maven.version}
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.4
+ org.codehaus.mojo
+ findbugs-maven-plugin
+ ${findbugs-maven-plugin.version}org.codehaus.mojobuild-helper-maven-plugin
- 1.8
+ ${build-helper-maven-plugin.version}validate
@@ -937,7 +991,7 @@
org.codehaus.mojobuildnumber-maven-plugin
- 1.1
+ ${buildnumber-maven-plugin.version}validate
@@ -954,7 +1008,7 @@
org.eclipse.m2elifecycle-mapping
- 1.0.0
+ ${lifecycle-mapping.version}
@@ -975,23 +1029,18 @@
-
- org.apache.maven.plugins
- maven-project-info-reports-plugin
- 2.7
-
- false
-
-
-
- org.apache.maven.plugins
- maven-clean-plugin
- 3.0.0
-
-
+ ro.isdc.wro4jwro4j-maven-plugin
- 1.7.9
+ ${wro4j-maven-plugin.version}
+
+
+
+ org.mockito
+ mockito-core
+ 2.18.0
+
+
@@ -1000,8 +1049,14 @@
org.apache.maven.pluginsmaven-enforcer-plugin
- 1.4
- false
+ ${maven-enforcer-plugin.version}
+
+
+ de.skuzzle.enforcer
+ restrict-imports-enforcer-rule
+ ${restrict-imports.enforcer.version}
+
+ clean
@@ -1011,14 +1066,32 @@
- [3.0.2,)
+ [3.6.3,)
- ${enforced.java.version}
+ [${maven.compiler.target},)
+
+ banned-illegal-imports
+ process-sources
+
+ enforce
+
+
+
+
+ true
+ Use Fasterxml Jackson 2 dependency in place of org.codehaus Jackson 1
+
+ org.codehaus.jackson.**
+
+
+
+
+
@@ -1052,6 +1125,16 @@
${basedir}/findbugs-exclude.xml
+
+
+ org.owasp
+ dependency-check-maven
+
@@ -1202,7 +1285,6 @@
org.apache.maven.pluginsmaven-javadoc-plugin
- ${javadoc-maven-plugin.version}true
@@ -1230,8 +1312,6 @@
maven-compiler-plugintrue
- ${javac.version}
- ${javac.version}9999
@@ -1250,7 +1330,7 @@
jdk.toolsjdk.tools
- 1.8
+ ${jdk.tools.version}system${java.home}/../lib/tools.jar
@@ -1263,6 +1343,12 @@
aws
+
+ org.apache.hadoop
+ hadoop-cloud-storage
+ runtime
+ ${hadoop.version}
+ org.apache.hadoophadoop-aws
@@ -1277,22 +1363,34 @@
azure
+
+ org.apache.hadoop
+ hadoop-cloud-storage
+ runtime
+ ${hadoop.version}
+ org.apache.hadoophadoop-azureruntime${hadoop.version}
+
+ org.apache.hadoop
+ hadoop-azure-datalake
+ runtime
+ ${hadoop.version}
+
+
org.apache.maven.pluginsmaven-javadoc-plugin
- ${javadoc-maven-plugin.version}aggregate
diff --git a/tez-api/pom.xml b/tez-api/pom.xml
index 78dd415572..4e6c27e18f 100644
--- a/tez-api/pom.xml
+++ b/tez-api/pom.xml
@@ -20,10 +20,14 @@
org.apache.teztez
- 0.9.1-SNAPSHOT
+ 0.10.5-SNAPSHOTtez-api
+
+ false
+
+
org.slf4j
@@ -107,9 +111,18 @@
org.mockito
- mockito-all
+ mockito-core
+ test
+
+
+ org.bouncycastle
+ bcprov-jdk18ontest
+
+ org.xerial.snappy
+ snappy-java
+
@@ -141,30 +154,26 @@
apache-rat-plugin
- org.apache.hadoop
- hadoop-maven-plugins
+ com.github.os72
+ protoc-jar-maven-plugin
- compile-protocgenerate-sources
- protoc
+ run
- ${protobuf.version}
+ com.google.protobuf:protoc:${protobuf.version}${protoc.path}
-
- ${basedir}/src/main/proto
-
-
- ${basedir}/src/main/proto
-
- DAGApiRecords.proto
- DAGClientAMProtocol.proto
- Events.proto
-
-
-
+ none
+
+ ${basedir}/src/main/proto
+
+
+
+ ${project.build.directory}/generated-sources/java
+
+
@@ -207,7 +216,7 @@
hadoop27
- true
+ false
@@ -219,12 +228,21 @@
hadoop28
+
+ true
+ org.apache.hadoophadoop-hdfs-client${hadoop.version}
+
+ org.apache.hadoop
+ hadoop-hdfs
+ test
+ ${hadoop.version}
+
diff --git a/tez-api/src/main/java/org/apache/tez/client/AMConfiguration.java b/tez-api/src/main/java/org/apache/tez/client/AMConfiguration.java
index 238b155010..1b61c45d05 100644
--- a/tez-api/src/main/java/org/apache/tez/client/AMConfiguration.java
+++ b/tez-api/src/main/java/org/apache/tez/client/AMConfiguration.java
@@ -23,7 +23,6 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.yarn.api.records.LocalResource;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.tez.dag.api.TezConfiguration;
import com.google.common.collect.Maps;
@@ -34,7 +33,6 @@ class AMConfiguration {
private Map amLocalResources = Maps.newHashMap();
private TezConfiguration tezConf;
private Credentials credentials;
- private YarnConfiguration yarnConfig;
private LocalResource binaryConfLRsrc;
AMConfiguration(TezConfiguration tezConf, Map localResources,
@@ -64,10 +62,6 @@ void setCredentials(Credentials credentials) {
void setTezConfiguration(TezConfiguration tezConf) {
this.tezConf = tezConf;
}
-
- void setYarnConfiguration(YarnConfiguration yarnConf) {
- this.yarnConfig = yarnConf;
- }
String getQueueName() {
return this.tezConf.get(TezConfiguration.TEZ_QUEUE_NAME);
@@ -81,10 +75,6 @@ TezConfiguration getTezConfiguration() {
return tezConf;
}
- YarnConfiguration getYarnConfiguration() {
- return yarnConfig;
- }
-
Credentials getCredentials() {
return credentials;
}
diff --git a/tez-api/src/main/java/org/apache/tez/client/CallerContext.java b/tez-api/src/main/java/org/apache/tez/client/CallerContext.java
index 809cf47d8e..f6c67cfe9c 100644
--- a/tez-api/src/main/java/org/apache/tez/client/CallerContext.java
+++ b/tez-api/src/main/java/org/apache/tez/client/CallerContext.java
@@ -24,7 +24,7 @@
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
@Public
@Unstable
diff --git a/tez-api/src/main/java/org/apache/tez/client/FrameworkClient.java b/tez-api/src/main/java/org/apache/tez/client/FrameworkClient.java
index b3e084c27c..a1a0b8a5e8 100644
--- a/tez-api/src/main/java/org/apache/tez/client/FrameworkClient.java
+++ b/tez-api/src/main/java/org/apache/tez/client/FrameworkClient.java
@@ -21,21 +21,39 @@
import java.io.IOException;
import org.apache.hadoop.classification.InterfaceAudience.Private;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.client.api.YarnClientApplication;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.tez.common.RPCUtil;
import org.apache.tez.common.ReflectionUtils;
+import org.apache.tez.dag.api.DAG;
+import org.apache.tez.dag.api.DAGSubmissionTimedOut;
+import org.apache.tez.dag.api.DagTypeConverters;
import org.apache.tez.dag.api.TezConfiguration;
import org.apache.tez.dag.api.TezException;
import org.apache.tez.dag.api.TezReflectionException;
import org.apache.tez.dag.api.TezUncheckedException;
+import org.apache.tez.dag.api.client.DAGClient;
+import org.apache.tez.dag.api.client.DAGClientImpl;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolBlockingPB;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusRequestProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusResponseProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.ShutdownSessionRequestProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.SubmitDAGRequestProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.SubmitDAGResponseProto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.protobuf.ServiceException;
@Private
public abstract class FrameworkClient {
+ protected static final Logger LOG = LoggerFactory.getLogger(FrameworkClient.class);
public static FrameworkClient createFrameworkClient(TezConfiguration tezConf) {
@@ -58,10 +76,8 @@ public static FrameworkClient createFrameworkClient(TezConfiguration tezConf) {
*
* @param tezConf the {@link org.apache.tez.dag.api.TezConfiguration} instance being used by the
* cluster
- * @param yarnConf the {@link org.apache.hadoop.yarn.conf.YarnConfiguration} instance being used
- * by the cluster
*/
- public abstract void init(TezConfiguration tezConf, YarnConfiguration yarnConf);
+ public abstract void init(TezConfiguration tezConf);
public abstract void start();
@@ -78,6 +94,104 @@ public abstract ApplicationId submitApplication(ApplicationSubmissionContext app
public abstract ApplicationReport getApplicationReport(ApplicationId appId) throws YarnException, IOException;
+ public abstract String getAmHost();
+ public abstract int getAmPort();
+
public abstract boolean isRunning() throws IOException;
+ public TezAppMasterStatus getAMStatus(Configuration conf, ApplicationId appId,
+ UserGroupInformation ugi) throws TezException, ServiceException, IOException {
+ DAGClientAMProtocolBlockingPB proxy = getProxy(conf, appId, ugi);
+
+ if (proxy == null) {
+ return TezAppMasterStatus.INITIALIZING;
+ }
+ GetAMStatusResponseProto response =
+ proxy.getAMStatus(null, GetAMStatusRequestProto.newBuilder().build());
+ return DagTypeConverters.convertTezAppMasterStatusFromProto(response.getStatus());
+ }
+
+ public DAGClient submitDag(DAG dag, SubmitDAGRequestProto request, String clientName,
+ ApplicationId sessionAppId, long clientTimeout, UserGroupInformation ugi, TezConfiguration tezConf)
+ throws IOException, TezException, DAGSubmissionTimedOut {
+ DAGClientAMProtocolBlockingPB proxy = null;
+ try {
+ proxy = waitForProxy(clientTimeout, tezConf, sessionAppId, ugi);
+ } catch (InterruptedException e) {
+ throw new IOException("Interrupted while trying to create a connection to the AM", e);
+ }
+ if (proxy == null) {
+ try {
+ LOG.warn("DAG submission to session timed out, stopping session");
+ stop();
+ } catch (Throwable t) {
+ LOG.info("Got an exception when trying to stop session", t);
+ }
+ throw new DAGSubmissionTimedOut("Could not submit DAG to Tez Session"
+ + ", timed out after " + clientTimeout + " seconds");
+ }
+
+ String dagId = null;
+ try {
+ SubmitDAGResponseProto response = proxy.submitDAG(null, request);
+ // the following check is only for testing since the final class
+ // SubmitDAGResponseProto cannot be mocked
+ if (response != null) {
+ dagId = response.getDagId();
+ }
+ } catch (ServiceException e) {
+ RPCUtil.unwrapAndThrowException(e);
+ }
+
+ LOG.info("Submitted dag to TezSession"
+ + ", sessionName=" + clientName
+ + ", applicationId=" + sessionAppId
+ + ", dagId=" + dagId
+ + ", dagName=" + dag.getName());
+ return getDAGClient(sessionAppId, dagId, tezConf, ugi);
+ }
+
+ protected DAGClientAMProtocolBlockingPB waitForProxy(long clientTimeout, Configuration conf,
+ ApplicationId sessionAppId, UserGroupInformation ugi)
+ throws IOException, TezException, InterruptedException {
+ long startTime = System.currentTimeMillis();
+ long endTime = startTime + (clientTimeout * 1000);
+ DAGClientAMProtocolBlockingPB proxy = null;
+ while (true) {
+ proxy = TezClientUtils.getAMProxy(this, conf, sessionAppId, ugi);
+ if (proxy != null) {
+ break;
+ }
+ Thread.sleep(100L);
+ if (clientTimeout != -1 && System.currentTimeMillis() > endTime) {
+ break;
+ }
+ }
+ return proxy;
+ }
+
+ /**
+ * Shuts down session and returns a boolean=true if a proxy was successfully created and through
+ * that proxy a shutdownSession was called.
+ */
+ public boolean shutdownSession(Configuration conf, ApplicationId sessionAppId,
+ UserGroupInformation ugi) throws TezException, IOException, ServiceException {
+ DAGClientAMProtocolBlockingPB proxy = getProxy(conf, sessionAppId, ugi);
+ if (proxy != null) {
+ ShutdownSessionRequestProto request = ShutdownSessionRequestProto.newBuilder().build();
+ proxy.shutdownSession(null, request);
+ return true;
+ }
+ return false;
+ }
+
+ protected DAGClientAMProtocolBlockingPB getProxy(Configuration conf, ApplicationId sessionAppId,
+ UserGroupInformation ugi) throws TezException, IOException {
+ return TezClientUtils.getAMProxy(this, conf, sessionAppId, ugi);
+ }
+
+ public DAGClient getDAGClient(ApplicationId appId, String dagId, TezConfiguration tezConf,
+ UserGroupInformation ugi) {
+ return new DAGClientImpl(appId, dagId, tezConf, this, ugi);
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/client/TezClient.java b/tez-api/src/main/java/org/apache/tez/client/TezClient.java
index 65ce0fb6ed..937346cacd 100644
--- a/tez-api/src/main/java/org/apache/tez/client/TezClient.java
+++ b/tez-api/src/main/java/org/apache/tez/client/TezClient.java
@@ -22,7 +22,6 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.NumberFormat;
-import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -30,15 +29,17 @@
import java.util.concurrent.TimeUnit;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import javax.annotation.Nullable;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.tez.common.JavaOptsChecker;
-import org.apache.tez.common.RPCUtil;
import org.apache.tez.common.TezCommonUtils;
import org.apache.tez.common.counters.Limits;
import org.apache.tez.dag.api.TezConfigurationConstants;
@@ -56,7 +57,6 @@
import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.hadoop.yarn.api.records.LocalResourceType;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.util.Time;
@@ -75,15 +75,11 @@
import org.apache.tez.dag.api.client.DAGClient;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolBlockingPB;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusRequestProto;
-import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusResponseProto;
-import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.ShutdownSessionRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.SubmitDAGRequestProto;
-import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.SubmitDAGResponseProto;
-import org.apache.tez.dag.api.client.DAGClientImpl;
import org.apache.tez.dag.api.records.DAGProtos.DAGPlan;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.protobuf.ServiceException;
@@ -109,7 +105,11 @@
public class TezClient {
private static final Logger LOG = LoggerFactory.getLogger(TezClient.class);
-
+
+ private static final String appIdStrPrefix = "application";
+ private static final String APPLICATION_ID_PREFIX = appIdStrPrefix + '_';
+ private static final long PREWARM_WAIT_MS = 500;
+
@VisibleForTesting
static final String NO_CLUSTER_DIAGNOSTICS_MSG = "No cluster diagnostics found.";
@@ -119,7 +119,8 @@ public class TezClient {
private ApplicationId lastSubmittedAppId;
@VisibleForTesting
final AMConfiguration amConfig;
- private FrameworkClient frameworkClient;
+ @VisibleForTesting
+ FrameworkClient frameworkClient;
private String diagnostics;
@VisibleForTesting
final boolean isSession;
@@ -139,7 +140,7 @@ public class TezClient {
@VisibleForTesting
final ServicePluginsDescriptor servicePluginsDescriptor;
private JavaOptsChecker javaOptsChecker = null;
-
+ private DAGClient prewarmDagClient = null;
private int preWarmDAGCounter = 0;
/* max submitDAG request size through IPC; beyond this we transfer them in the same way we transfer local resource */
@@ -150,9 +151,11 @@ public class TezClient {
private ScheduledExecutorService amKeepAliveService;
+ private final Map ugiMap;
+
private TezClient(String name, TezConfiguration tezConf) {
this(name, tezConf, tezConf.getBoolean(
- TezConfiguration.TEZ_AM_SESSION_MODE, TezConfiguration.TEZ_AM_SESSION_MODE_DEFAULT));
+ TezConfiguration.TEZ_AM_SESSION_MODE, TezConfiguration.TEZ_AM_SESSION_MODE_DEFAULT));
}
@Private
@@ -193,6 +196,7 @@ protected TezClient(String name, TezConfiguration tezConf, boolean isSession,
LOG.warn("The host name of the client the tez application was submitted from was unable to be retrieved", e);
}
+ this.ugiMap = new HashMap<>();
this.amConfig = new AMConfiguration(tezConf, localResources, credentials);
this.apiVersionInfo = new TezApiVersionInfo();
this.servicePluginsDescriptor = servicePluginsDescriptor;
@@ -299,7 +303,7 @@ public static TezClient create(String name, TezConfiguration tezConf, boolean is
}
/**
- * Add local files for the DAG App Master. These may be files, archives,
+ * Add local files for the DAG App Master. These may be files, archives,
* jars etc.
*
* In non-session mode these will be added to the files of the App Master
@@ -317,17 +321,17 @@ public static TezClient create(String name, TezConfiguration tezConf, boolean is
* accumulate across DAG submissions and are never removed from the classpath.
* Only LocalResourceType.FILE is supported. All files will be treated as
* private.
- *
+ *
* @param localFiles the files to be made available in the AM
*/
public synchronized void addAppMasterLocalFiles(Map localFiles) {
- Preconditions.checkNotNull(localFiles);
+ Objects.requireNonNull(localFiles);
if (isSession && sessionStarted.get()) {
additionalLocalResources.putAll(localFiles);
}
amConfig.addAMLocalResources(localFiles);
}
-
+
/**
* If the next DAG App Master needs different local files, then use this
* method to clear the local files and then add the new local files
@@ -337,7 +341,7 @@ public synchronized void addAppMasterLocalFiles(Map local
public synchronized void clearAppMasterLocalFiles() {
amConfig.clearAMLocalResources();
}
-
+
/**
* Set security credentials to be used inside the app master, if needed. Tez App
* Master needs credentials to access the staging directory and for most HDFS
@@ -347,7 +351,7 @@ public synchronized void clearAppMasterLocalFiles() {
* credentials must be supplied by the user. These will be used by the App
* Master for the next DAG. In session mode, credentials, if needed, must be
* set before calling start()
- *
+ *
* @param credentials credentials
*/
public synchronized void setAppMasterCredentials(Credentials credentials) {
@@ -376,100 +380,184 @@ public synchronized void setHistoryLogLevel(HistoryLogLevel historyLogLevel) {
* @throws IOException
*/
public synchronized void start() throws TezException, IOException {
- amConfig.setYarnConfiguration(new YarnConfiguration(amConfig.getTezConfiguration()));
-
- frameworkClient = createFrameworkClient();
- frameworkClient.init(amConfig.getTezConfiguration(), amConfig.getYarnConfiguration());
- frameworkClient.start();
-
- if (this.amConfig.getTezConfiguration().getBoolean(
- TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_ENABLED,
- TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_ENABLED_DEFAULT)) {
- String javaOptsCheckerClassName = this.amConfig.getTezConfiguration().get(
- TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_CLASS, "");
- if (!javaOptsCheckerClassName.isEmpty()) {
- try {
- javaOptsChecker = ReflectionUtils.createClazzInstance(javaOptsCheckerClassName);
- } catch (Exception e) {
- LOG.warn("Failed to initialize configured Java Opts Checker"
- + " (" + TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_CLASS
- + ") , checkerClass=" + javaOptsCheckerClassName
- + ". Disabling checker.", e);
- javaOptsChecker = null;
- }
- } else {
- javaOptsChecker = new JavaOptsChecker();
- }
-
- }
-
+ startFrameworkClient();
+ setupJavaOptsChecker();
if (isSession) {
LOG.info("Session mode. Starting session.");
TezClientUtils.processTezLocalCredentialsFile(sessionCredentials,
amConfig.getTezConfiguration());
-
- Map tezJarResources = getTezJarResources(sessionCredentials);
-
+
clientTimeout = amConfig.getTezConfiguration().getInt(
TezConfiguration.TEZ_SESSION_CLIENT_TIMEOUT_SECS,
TezConfiguration.TEZ_SESSION_CLIENT_TIMEOUT_SECS_DEFAULT);
-
+
try {
if (sessionAppId == null) {
sessionAppId = createApplication();
}
-
- // Add session token for shuffle
- TezClientUtils.createSessionToken(sessionAppId.toString(),
- jobTokenSecretManager, sessionCredentials);
-
- ApplicationSubmissionContext appContext =
- TezClientUtils.createApplicationSubmissionContext(
- sessionAppId,
- null, clientName, amConfig,
- tezJarResources, sessionCredentials, usingTezArchiveDeploy, apiVersionInfo,
- servicePluginsDescriptor, javaOptsChecker);
-
- // Set Tez Sessions to not retry on AM crashes if recovery is disabled
- if (!amConfig.getTezConfiguration().getBoolean(
- TezConfiguration.DAG_RECOVERY_ENABLED,
- TezConfiguration.DAG_RECOVERY_ENABLED_DEFAULT)) {
- appContext.setMaxAppAttempts(1);
- }
+
+ ApplicationSubmissionContext appContext = setupApplicationContext();
frameworkClient.submitApplication(appContext);
ApplicationReport appReport = frameworkClient.getApplicationReport(sessionAppId);
LOG.info("The url to track the Tez Session: " + appReport.getTrackingUrl());
sessionStarted.set(true);
} catch (YarnException e) {
+ cleanStagingDir();
+ throw new TezException(e);
+ } catch (IOException e) {
+ cleanStagingDir();
throw new TezException(e);
}
- long amClientKeepAliveTimeoutIntervalMillis =
- TezCommonUtils.getAMClientHeartBeatTimeoutMillis(amConfig.getTezConfiguration());
- // Poll at minimum of 1 second interval
- long pollPeriod = TezCommonUtils.
- getAMClientHeartBeatPollIntervalMillis(amConfig.getTezConfiguration(),
- amClientKeepAliveTimeoutIntervalMillis, 10);
-
- boolean isLocal = amConfig.getTezConfiguration().getBoolean(
- TezConfiguration.TEZ_LOCAL_MODE, TezConfiguration.TEZ_LOCAL_MODE_DEFAULT);
- if (!isLocal && amClientKeepAliveTimeoutIntervalMillis > 0) {
- amKeepAliveService = Executors.newSingleThreadScheduledExecutor(
- new ThreadFactoryBuilder()
- .setDaemon(true).setNameFormat("AMKeepAliveThread #%d").build());
- amKeepAliveService.scheduleWithFixedDelay(new Runnable() {
-
- private DAGClientAMProtocolBlockingPB proxy;
-
- @Override
- public void run() {
- proxy = sendAMHeartbeat(proxy);
- }
- }, pollPeriod, pollPeriod, TimeUnit.MILLISECONDS);
+ startClientHeartbeat();
+ this.stagingFs = FileSystem.get(amConfig.getTezConfiguration());
+ }
+ }
+
+ private void cleanStagingDir() {
+ Configuration conf = amConfig.getTezConfiguration();
+ String appId = sessionAppId.toString();
+ Path stagingDir = TezCommonUtils.getTezSystemStagingPath(conf, appId);
+ boolean isStgDeleted = false;
+ try {
+ FileSystem fs = stagingDir.getFileSystem(conf);
+ isStgDeleted = fs.delete(stagingDir, true);
+ } catch (IOException ioe) {
+ LOG.error("Error deleting staging dir " + stagingDir, ioe);
+ } finally {
+ LOG.info("Staging dir {}, deleted:{} ", stagingDir, isStgDeleted);
+ }
+ }
+
+ public synchronized TezClient getClient(String appIdStr) throws IOException, TezException {
+ return getClient(appIdfromString(appIdStr));
+ }
+
+ /**
+ * Alternative to start() that explicitly sets sessionAppId and doesn't start a new AM.
+ * The caller of getClient is responsible for initializing the new TezClient with a
+ * Configuration compatible with the existing AM. It is expected the caller has cached the
+ * original Configuration (e.g. in Zookeeper).
+ *
+ * In contrast to "start", no resources are localized. It is the responsibility of the caller to
+ * ensure that existing localized resources and staging dirs are still valid.
+ *
+ * @param appId
+ * @return 'this' just as a convenience for fluent style chaining
+ */
+ public synchronized TezClient getClient(ApplicationId appId) throws TezException, IOException {
+ sessionAppId = appId;
+ startFrameworkClient();
+ setupJavaOptsChecker();
+
+ if (!isSession) {
+ String msg = "Must be in session mode to bind TezClient to existing AM";
+ LOG.error(msg);
+ throw new IllegalStateException(msg);
+ }
+
+ LOG.info("Session mode. Reconnecting to session: " + sessionAppId.toString());
+
+ clientTimeout = amConfig.getTezConfiguration().getInt(
+ TezConfiguration.TEZ_SESSION_CLIENT_TIMEOUT_SECS,
+ TezConfiguration.TEZ_SESSION_CLIENT_TIMEOUT_SECS_DEFAULT);
+
+ try {
+ setupApplicationContext();
+ ApplicationReport appReport = frameworkClient.getApplicationReport(sessionAppId);
+ LOG.info("The url to track the Tez Session: " + appReport.getTrackingUrl());
+ sessionStarted.set(true);
+ } catch (YarnException e) {
+ cleanStagingDir();
+ throw new TezException(e);
+ } catch (IOException e) {
+ cleanStagingDir();
+ throw new TezException(e);
+ }
+
+ startClientHeartbeat();
+ this.stagingFs = FileSystem.get(amConfig.getTezConfiguration());
+ return this;
+ }
+
+ private void startFrameworkClient() {
+ frameworkClient = createFrameworkClient();
+ frameworkClient.init(amConfig.getTezConfiguration());
+ frameworkClient.start();
+ }
+
+ private ApplicationSubmissionContext setupApplicationContext() throws IOException, YarnException {
+ TezClientUtils.processTezLocalCredentialsFile(sessionCredentials,
+ amConfig.getTezConfiguration());
+
+ Map tezJarResources = getTezJarResources(sessionCredentials);
+ // Add session token for shuffle
+ TezClientUtils.createSessionToken(sessionAppId.toString(),
+ jobTokenSecretManager, sessionCredentials);
+
+ ApplicationSubmissionContext appContext =
+ TezClientUtils.createApplicationSubmissionContext(
+ sessionAppId,
+ null, clientName, amConfig,
+ tezJarResources, sessionCredentials, usingTezArchiveDeploy, apiVersionInfo,
+ servicePluginsDescriptor, javaOptsChecker);
+
+ // Set Tez Sessions to not retry on AM crashes if recovery is disabled
+ if (!amConfig.getTezConfiguration().getBoolean(
+ TezConfiguration.DAG_RECOVERY_ENABLED,
+ TezConfiguration.DAG_RECOVERY_ENABLED_DEFAULT)) {
+ appContext.setMaxAppAttempts(1);
+ }
+ return appContext;
+ }
+
+ private void setupJavaOptsChecker() {
+ if (this.amConfig.getTezConfiguration().getBoolean(
+ TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_ENABLED,
+ TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_ENABLED_DEFAULT)) {
+ String javaOptsCheckerClassName = this.amConfig.getTezConfiguration().get(
+ TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_CLASS, "");
+ if (!javaOptsCheckerClassName.isEmpty()) {
+ try {
+ javaOptsChecker = ReflectionUtils.createClazzInstance(javaOptsCheckerClassName);
+ } catch (Exception e) {
+ LOG.warn("Failed to initialize configured Java Opts Checker"
+ + " (" + TezConfiguration.TEZ_CLIENT_JAVA_OPTS_CHECKER_CLASS
+ + ") , checkerClass=" + javaOptsCheckerClassName
+ + ". Disabling checker.", e);
+ javaOptsChecker = null;
+ }
+ } else {
+ javaOptsChecker = new JavaOptsChecker();
}
- this.stagingFs = FileSystem.get(amConfig.getTezConfiguration());
+ }
+ }
+
+ private void startClientHeartbeat() {
+ long amClientKeepAliveTimeoutIntervalMillis =
+ TezCommonUtils.getAMClientHeartBeatTimeoutMillis(amConfig.getTezConfiguration());
+ // Poll at minimum of 1 second interval
+ long pollPeriod = TezCommonUtils.
+ getAMClientHeartBeatPollIntervalMillis(amConfig.getTezConfiguration(),
+ amClientKeepAliveTimeoutIntervalMillis, 10);
+
+ boolean isLocal = amConfig.getTezConfiguration().getBoolean(
+ TezConfiguration.TEZ_LOCAL_MODE, TezConfiguration.TEZ_LOCAL_MODE_DEFAULT);
+ if (!isLocal && amClientKeepAliveTimeoutIntervalMillis > 0) {
+ amKeepAliveService = Executors.newSingleThreadScheduledExecutor(
+ new ThreadFactoryBuilder()
+ .setDaemon(true).setNameFormat("AMKeepAliveThread #%d").build());
+ amKeepAliveService.scheduleWithFixedDelay(new Runnable() {
+
+ private DAGClientAMProtocolBlockingPB proxy;
+
+ @Override
+ public void run() {
+ proxy = sendAMHeartbeat(proxy);
+ }
+ }, pollPeriod, pollPeriod, TimeUnit.MILLISECONDS);
}
}
@@ -481,7 +569,8 @@ public DAGClientAMProtocolBlockingPB sendAMHeartbeat(DAGClientAMProtocolBlocking
try {
if (proxy == null) {
try {
- proxy = waitForProxy();
+ proxy = frameworkClient.waitForProxy(clientTimeout, amConfig.getTezConfiguration(),
+ sessionAppId, getUgi());
} catch (InterruptedException e) {
LOG.debug("Interrupted while trying to create a connection to the AM", e);
} catch (SessionNotRunning e) {
@@ -508,7 +597,7 @@ public DAGClientAMProtocolBlockingPB sendAMHeartbeat(DAGClientAMProtocolBlocking
* cluster. In session mode, it submits the DAG to the session App Master. It
* blocks until either the DAG is submitted to the session or configured
* timeout period expires. Cleans up session if the submission timed out.
- *
+ *
* @param dag
* DAG to be submitted to Session
* @return DAGClient to monitor the DAG
@@ -516,23 +605,51 @@ public DAGClientAMProtocolBlockingPB sendAMHeartbeat(DAGClientAMProtocolBlocking
* @throws IOException
* @throws DAGSubmissionTimedOut
* if submission timed out
- */
+ */
public synchronized DAGClient submitDAG(DAG dag) throws TezException, IOException {
- if (isSession) {
- return submitDAGSession(dag);
- } else {
- return submitDAGApplication(dag);
+ DAGClient result = isSession ? submitDAGSession(dag) : submitDAGApplication(dag);
+ if (result != null) {
+ closePrewarmDagClient(); // Assume the current DAG replaced the prewarm one; no need to kill.
}
+ return result;
+ }
+
+ private void killAndClosePrewarmDagClient(long waitTimeMs) {
+ if (prewarmDagClient == null) {
+ return;
+ }
+ try {
+ prewarmDagClient.tryKillDAG();
+ if (waitTimeMs > 0) {
+ LOG.info("Waiting for prewarm DAG to shut down");
+ prewarmDagClient.waitForCompletion(waitTimeMs);
+ }
+ }
+ catch (Exception ex) {
+ LOG.warn("Failed to shut down the prewarm DAG " + prewarmDagClient, ex);
+ }
+ closePrewarmDagClient();
+ }
+
+ private void closePrewarmDagClient() {
+ if (prewarmDagClient == null) {
+ return;
+ }
+ try {
+ prewarmDagClient.close();
+ } catch (Exception e) {
+ LOG.warn("Failed to close prewarm DagClient " + prewarmDagClient, e);
+ }
+ prewarmDagClient = null;
}
private DAGClient submitDAGSession(DAG dag) throws TezException, IOException {
- Preconditions.checkState(isSession == true,
- "submitDAG with additional resources applies to only session mode. " +
+ Preconditions.checkState(isSession,
+ "submitDAG with additional resources applies to only session mode. " +
"In non-session mode please specify all resources in the initial configuration");
-
+
verifySessionStateForSubmission();
- String dagId = null;
String callerContextStr = "";
if (dag.getCallerContext() != null) {
callerContextStr = ", callerContext=" + dag.getCallerContext().contextAsSimpleString();
@@ -542,7 +659,7 @@ private DAGClient submitDAGSession(DAG dag) throws TezException, IOException {
+ ", applicationId=" + sessionAppId
+ ", dagName=" + dag.getName()
+ callerContextStr);
-
+
if (!additionalLocalResources.isEmpty()) {
for (LocalResource lr : additionalLocalResources.values()) {
Preconditions.checkArgument(lr.getType() == LocalResourceType.FILE, "LocalResourceType: "
@@ -560,7 +677,7 @@ private DAGClient submitDAGSession(DAG dag) throws TezException, IOException {
requestBuilder.setAdditionalAmResources(DagTypeConverters
.convertFromLocalResources(additionalLocalResources));
}
-
+
additionalLocalResources.clear();
// if request size exceeds maxSubmitDAGRequestSizeThroughIPC, we serialize them to HDFS
@@ -570,54 +687,31 @@ private DAGClient submitDAGSession(DAG dag) throws TezException, IOException {
sessionAppId.toString()), TezConstants.TEZ_PB_PLAN_BINARY_NAME +
serializedSubmitDAGPlanRequestCounter.incrementAndGet());
- try (FSDataOutputStream fsDataOutputStream = stagingFs.create(dagPlanPath, false)) {
+ FileSystem fs = dagPlanPath.getFileSystem(stagingFs.getConf());
+ try (FSDataOutputStream fsDataOutputStream = fs.create(dagPlanPath, false)) {
LOG.info("Send dag plan using YARN local resources since it's too large"
+ ", dag plan size=" + request.getSerializedSize()
+ ", max dag plan size through IPC=" + maxSubmitDAGRequestSizeThroughIPC
+ ", max IPC message size= " + amConfig.getTezConfiguration().getInt(
CommonConfigurationKeys.IPC_MAXIMUM_DATA_LENGTH, CommonConfigurationKeys.IPC_MAXIMUM_DATA_LENGTH_DEFAULT));
request.writeTo(fsDataOutputStream);
- request = requestBuilder.clear().setSerializedRequestPath(stagingFs.resolvePath(dagPlanPath).toString()).build();
}
+ request = requestBuilder.clear().setSerializedRequestPath(fs.resolvePath(dagPlanPath).toString()).build();
}
- DAGClientAMProtocolBlockingPB proxy = null;
- try {
- proxy = waitForProxy();
- } catch (InterruptedException e) {
- throw new IOException("Interrupted while trying to create a connection to the AM", e);
- }
- if (proxy == null) {
- try {
- LOG.warn("DAG submission to session timed out, stopping session");
- stop();
- } catch (Throwable t) {
- LOG.info("Got an exception when trying to stop session", t);
- }
- throw new DAGSubmissionTimedOut("Could not submit DAG to Tez Session"
- + ", timed out after " + clientTimeout + " seconds");
- }
+ return frameworkClient.submitDag(dag, request, clientName, sessionAppId, clientTimeout,
+ getUgi(), amConfig.getTezConfiguration());
+ }
- try {
- SubmitDAGResponseProto response = proxy.submitDAG(null, request);
- // the following check is only for testing since the final class
- // SubmitDAGResponseProto cannot be mocked
- if (response != null) {
- dagId = response.getDagId();
- }
- } catch (ServiceException e) {
- RPCUtil.unwrapAndThrowException(e);
- }
+ private UserGroupInformation getUgi() throws IOException {
+ String userName = UserGroupInformation.getCurrentUser().getUserName();
+ return ugiMap.computeIfAbsent(userName,
+ v -> UserGroupInformation.createRemoteUser(userName));
+ }
- LOG.info("Submitted dag to TezSession"
- + ", sessionName=" + clientName
- + ", applicationId=" + sessionAppId
- + ", dagId=" + dagId
- + ", dagName=" + dag.getName());
- return new DAGClientImpl(sessionAppId, dagId,
- amConfig.getTezConfiguration(),
- amConfig.getYarnConfiguration(),
- frameworkClient);
+ @VisibleForTesting
+ protected long getPrewarmWaitTimeMs() {
+ return PREWARM_WAIT_MS;
}
/**
@@ -627,6 +721,7 @@ private DAGClient submitDAGSession(DAG dag) throws TezException, IOException {
* @throws IOException
*/
public synchronized void stop() throws TezException, IOException {
+ killAndClosePrewarmDagClient(getPrewarmWaitTimeMs());
try {
if (amKeepAliveService != null) {
amKeepAliveService.shutdownNow();
@@ -638,39 +733,34 @@ public synchronized void stop() throws TezException, IOException {
sessionStopped.set(true);
boolean sessionShutdownSuccessful = false;
try {
- DAGClientAMProtocolBlockingPB proxy = getAMProxy(sessionAppId);
- if (proxy != null) {
- ShutdownSessionRequestProto request =
- ShutdownSessionRequestProto.newBuilder().build();
- proxy.shutdownSession(null, request);
- sessionShutdownSuccessful = true;
- boolean asynchronousStop = amConfig.getTezConfiguration().getBoolean(
- TezConfiguration.TEZ_CLIENT_ASYNCHRONOUS_STOP,
- TezConfiguration.TEZ_CLIENT_ASYNCHRONOUS_STOP_DEFAULT);
- if (!asynchronousStop) {
- LOG.info("Waiting until application is in a final state");
- long currentTimeMillis = System.currentTimeMillis();
- long timeKillIssued = currentTimeMillis;
- long killTimeOut = amConfig.getTezConfiguration().getLong(
- TezConfiguration.TEZ_CLIENT_HARD_KILL_TIMEOUT_MS,
- TezConfiguration.TEZ_CLIENT_HARD_KILL_TIMEOUT_MS_DEFAULT);
- ApplicationReport appReport = frameworkClient
- .getApplicationReport(sessionAppId);
- while ((currentTimeMillis < timeKillIssued + killTimeOut)
- && !isJobInTerminalState(appReport.getYarnApplicationState())) {
- try {
- Thread.sleep(1000L);
- } catch (InterruptedException ie) {
- /** interrupted, just break */
- break;
- }
- currentTimeMillis = System.currentTimeMillis();
- appReport = frameworkClient.getApplicationReport(sessionAppId);
+ sessionShutdownSuccessful = frameworkClient
+ .shutdownSession(amConfig.getTezConfiguration(), sessionAppId, getUgi());
+ boolean asynchronousStop = amConfig.getTezConfiguration().getBoolean(
+ TezConfiguration.TEZ_CLIENT_ASYNCHRONOUS_STOP,
+ TezConfiguration.TEZ_CLIENT_ASYNCHRONOUS_STOP_DEFAULT);
+ if (!asynchronousStop && sessionShutdownSuccessful) {
+ LOG.info("Waiting until application is in a final state");
+ long currentTimeMillis = System.currentTimeMillis();
+ long timeKillIssued = currentTimeMillis;
+ long killTimeOut = amConfig.getTezConfiguration().getLong(
+ TezConfiguration.TEZ_CLIENT_HARD_KILL_TIMEOUT_MS,
+ TezConfiguration.TEZ_CLIENT_HARD_KILL_TIMEOUT_MS_DEFAULT);
+ ApplicationReport appReport = frameworkClient
+ .getApplicationReport(sessionAppId);
+ while ((currentTimeMillis < timeKillIssued + killTimeOut)
+ && !isJobInTerminalState(appReport.getYarnApplicationState())) {
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException ie) {
+ /** interrupted, just break */
+ break;
}
+ currentTimeMillis = System.currentTimeMillis();
+ appReport = frameworkClient.getApplicationReport(sessionAppId);
+ }
- if (!isJobInTerminalState(appReport.getYarnApplicationState())) {
- frameworkClient.killApplication(sessionAppId);
- }
+ if (!isJobInTerminalState(appReport.getYarnApplicationState())) {
+ frameworkClient.killApplication(sessionAppId);
}
}
} catch (TezException e) {
@@ -714,7 +804,7 @@ private boolean isJobInTerminalState(YarnApplicationState yarnApplicationState)
public String getClientName() {
return clientName;
}
-
+
@Private
@VisibleForTesting
public synchronized ApplicationId getAppMasterApplicationId() {
@@ -727,16 +817,16 @@ public synchronized ApplicationId getAppMasterApplicationId() {
/**
* Get the status of the App Master executing the DAG
- * In non-session mode it returns the status of the last submitted DAG App Master
+ * In non-session mode it returns the status of the last submitted DAG App Master
* In session mode, it returns the status of the App Master hosting the session
- *
+ *
* @return State of the session
* @throws TezException
* @throws IOException
*/
public synchronized TezAppMasterStatus getAppMasterStatus() throws TezException, IOException {
- // Supporting per-DAG app master case since user may choose to run the same
- // code in that mode and the code should continue to work. Its easy to provide
+ // Supporting per-DAG app master case since user may choose to run the same
+ // code in that mode and the code should continue to work. Its easy to provide
// the correct view for per-DAG app master too.
ApplicationId appId = null;
if (isSession) {
@@ -765,14 +855,7 @@ public synchronized TezAppMasterStatus getAppMasterStatus() throws TezException,
return TezAppMasterStatus.SHUTDOWN;
case RUNNING:
try {
- DAGClientAMProtocolBlockingPB proxy = getAMProxy(appId);
- if (proxy == null) {
- return TezAppMasterStatus.INITIALIZING;
- }
- GetAMStatusResponseProto response = proxy.getAMStatus(null,
- GetAMStatusRequestProto.newBuilder().build());
- return DagTypeConverters.convertTezAppMasterStatusFromProto(
- response.getStatus());
+ return frameworkClient.getAMStatus(amConfig.getTezConfiguration(), appId, getUgi());
} catch (TezException e) {
LOG.info("Failed to retrieve AM Status via proxy", e);
} catch (ServiceException e) {
@@ -786,21 +869,21 @@ public synchronized TezAppMasterStatus getAppMasterStatus() throws TezException,
}
return TezAppMasterStatus.INITIALIZING;
}
-
+
/**
* API to help pre-allocate containers in session mode. In non-session mode
- * this is ignored. The pre-allocated containers may be re-used by subsequent
- * job DAGs to improve performance.
+ * this is ignored. The pre-allocated containers may be re-used by subsequent
+ * job DAGs to improve performance.
* The preWarm vertex should be configured and setup exactly
- * like the other vertices in the job DAGs so that the pre-allocated containers
+ * like the other vertices in the job DAGs so that the pre-allocated containers
* may be re-used by the subsequent DAGs to improve performance.
* The processor for the preWarmVertex may be used to pre-warm the containers
- * by pre-loading classes etc. It should be short-running so that pre-warming
+ * by pre-loading classes etc. It should be short-running so that pre-warming
* does not block real execution. Users can specify their custom processors or
* use the PreWarmProcessor from the runtime library.
* The parallelism of the preWarmVertex will determine the number of preWarmed
* containers.
- * Pre-warming is best efforts and among other factors is limited by the free
+ * Pre-warming is best efforts and among other factors is limited by the free
* resources on the cluster.
* @param preWarmVertex
* @throws TezException
@@ -846,7 +929,7 @@ public synchronized void preWarm(PreWarmVertex preWarmVertex,
}
verifySessionStateForSubmission();
-
+
DAG dag = org.apache.tez.dag.api.DAG.create(TezConstants.TEZ_PREWARM_DAG_NAME_PREFIX + "_"
+ preWarmDAGCounter++);
dag.addVertex(preWarmVertex);
@@ -859,13 +942,13 @@ public synchronized void preWarm(PreWarmVertex preWarmVertex,
"available", e);
}
if(isReady) {
- submitDAG(dag);
+ prewarmDagClient = submitDAG(dag);
} else {
throw new SessionNotReady("Tez AM not ready, could not submit DAG");
}
}
-
+
/**
* Wait till the DAG is ready to be submitted.
* In non-session mode this is a no-op since the application can be immediately
@@ -873,7 +956,7 @@ public synchronized void preWarm(PreWarmVertex preWarmVertex,
* In session mode, this waits for the session host to be ready to accept a DAG
* @throws IOException
* @throws TezException
- * @throws InterruptedException
+ * @throws InterruptedException
*/
@Evolving
public synchronized void waitTillReady() throws IOException, TezException, InterruptedException {
@@ -951,32 +1034,6 @@ protected FrameworkClient createFrameworkClient() {
return FrameworkClient.createFrameworkClient(amConfig.getTezConfiguration());
}
- @VisibleForTesting
- // for testing
- protected DAGClientAMProtocolBlockingPB getAMProxy(ApplicationId appId)
- throws TezException, IOException {
- return TezClientUtils.getAMProxy(
- frameworkClient, amConfig.getYarnConfiguration(), appId);
- }
-
- private DAGClientAMProtocolBlockingPB waitForProxy()
- throws IOException, TezException, InterruptedException {
- long startTime = System.currentTimeMillis();
- long endTime = startTime + (clientTimeout * 1000);
- DAGClientAMProtocolBlockingPB proxy = null;
- while (true) {
- proxy = getAMProxy(sessionAppId);
- if (proxy != null) {
- break;
- }
- Thread.sleep(100l);
- if (clientTimeout != -1 && System.currentTimeMillis() > endTime) {
- break;
- }
- }
- return proxy;
- }
-
private void verifySessionStateForSubmission() throws SessionNotRunning {
Preconditions.checkState(isSession, "Invalid without session mode");
if (!sessionStarted.get()) {
@@ -985,7 +1042,7 @@ private void verifySessionStateForSubmission() throws SessionNotRunning {
throw new SessionNotRunning("Session stopped by user");
}
}
-
+
private DAGClient submitDAGApplication(DAG dag)
throws TezException, IOException {
ApplicationId appId = createApplication();
@@ -998,7 +1055,7 @@ DAGClient submitDAGApplication(ApplicationId appId, DAG dag)
LOG.info("Submitting DAG application with id: " + appId);
try {
// Use the AMCredentials object in client mode, since this won't be re-used.
- // Ensures we don't fetch credentially unnecessarily if the user has already provided them.
+ // Ensures we don't fetch credentials unnecessarily if the user has already provided them.
Credentials credentials = amConfig.getCredentials();
if (credentials == null) {
credentials = new Credentials();
@@ -1024,7 +1081,7 @@ DAGClient submitDAGApplication(ApplicationId appId, DAG dag)
+ ", applicationId=" + appId
+ ", dagName=" + dag.getName()
+ callerContextStr);
-
+ TezCommonUtils.logCredentials(LOG, credentials, "appContext");
frameworkClient.submitApplication(appContext);
ApplicationReport appReport = frameworkClient.getApplicationReport(appId);
LOG.info("The url to track the Tez AM: " + appReport.getTrackingUrl());
@@ -1034,8 +1091,7 @@ DAGClient submitDAGApplication(ApplicationId appId, DAG dag)
}
// wait for dag in non-session mode to start running, so that we can start to getDAGStatus
waitNonSessionTillReady();
- return getDAGClient(appId, amConfig.getTezConfiguration(), amConfig.getYarnConfiguration(),
- frameworkClient);
+ return getDAGClient(appId, amConfig.getTezConfiguration(), frameworkClient, getUgi());
}
private ApplicationId createApplication() throws TezException, IOException {
@@ -1058,18 +1114,9 @@ private synchronized Map getTezJarResources(Credentials c
}
@Private
- static DAGClient getDAGClient(ApplicationId appId, TezConfiguration tezConf, YarnConfiguration
- yarnConf, FrameworkClient frameworkClient)
- throws IOException, TezException {
- return new DAGClientImpl(appId, getDefaultTezDAGID(appId), tezConf,
- yarnConf, frameworkClient);
- }
-
- @Private // Used only for MapReduce compatibility code
static DAGClient getDAGClient(ApplicationId appId, TezConfiguration tezConf,
- FrameworkClient frameworkClient)
- throws IOException, TezException {
- return getDAGClient(appId, tezConf, new YarnConfiguration(tezConf), frameworkClient);
+ FrameworkClient frameworkClient, UserGroupInformation ugi) throws IOException, TezException {
+ return frameworkClient.getDAGClient(appId, getDefaultTezDAGID(appId), tezConf, ugi);
}
// DO NOT CHANGE THIS. This code is replicated from TezDAGID.java
@@ -1211,4 +1258,40 @@ public TezClient build() {
servicePluginsDescriptor);
}
}
+
+ //Copied this helper method from
+ //org.apache.hadoop.yarn.api.records.ApplicationId in Hadoop 2.8+
+ //to simplify implementation on 2.7.x
+ @Public
+ @Unstable
+ public static ApplicationId appIdfromString(String appIdStr) {
+ if (!appIdStr.startsWith(APPLICATION_ID_PREFIX)) {
+ throw new IllegalArgumentException("Invalid ApplicationId prefix: "
+ + appIdStr + ". The valid ApplicationId should start with prefix "
+ + appIdStrPrefix);
+ }
+ try {
+ int pos1 = APPLICATION_ID_PREFIX.length() - 1;
+ int pos2 = appIdStr.indexOf('_', pos1 + 1);
+ if (pos2 < 0) {
+ throw new IllegalArgumentException("Invalid ApplicationId: "
+ + appIdStr);
+ }
+ long rmId = Long.parseLong(appIdStr.substring(pos1 + 1, pos2));
+ int appId = Integer.parseInt(appIdStr.substring(pos2 + 1));
+ ApplicationId applicationId = ApplicationId.newInstance(rmId, appId);
+ return applicationId;
+ } catch (NumberFormatException n) {
+ throw new IllegalArgumentException("Invalid ApplicationId: "
+ + appIdStr, n);
+ }
+ }
+
+ public String getAmHost() {
+ return frameworkClient == null ? null : frameworkClient.getAmHost();
+ }
+
+ public int getAmPort() {
+ return frameworkClient == null ? -1 : frameworkClient.getAmPort();
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/client/TezClientUtils.java b/tez-api/src/main/java/org/apache/tez/client/TezClientUtils.java
index f9316e5cf4..bae0174b3b 100644
--- a/tez-api/src/main/java/org/apache/tez/client/TezClientUtils.java
+++ b/tez-api/src/main/java/org/apache/tez/client/TezClientUtils.java
@@ -19,6 +19,7 @@
package org.apache.tez.client;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
@@ -27,7 +28,9 @@
import java.nio.ByteBuffer;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -37,11 +40,13 @@
import java.util.TreeMap;
import java.util.Vector;
import java.util.Map.Entry;
+import java.util.Objects;
import com.google.common.base.Strings;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.commons.math3.util.Precision;
+import org.apache.hadoop.fs.LocatedFileStatus;
+import org.apache.hadoop.fs.RemoteIterator;
import org.apache.tez.common.JavaOptsChecker;
import org.apache.tez.dag.api.records.DAGProtos.AMPluginDescriptorProto;
import org.apache.tez.serviceplugins.api.ServicePluginsDescriptor;
@@ -110,44 +115,39 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
@Private
-public class TezClientUtils {
+public final class TezClientUtils {
- private static Logger LOG = LoggerFactory.getLogger(TezClientUtils.class);
+ private static final Logger LOG = LoggerFactory.getLogger(TezClientUtils.class);
private static final int UTF8_CHUNK_SIZE = 16 * 1024;
- private static FileStatus[] getLRFileStatus(String fileName, Configuration conf) throws
- IOException {
- URI uri;
+ private TezClientUtils() {}
+
+ private static RemoteIterator getListFilesFileStatus(String configUri, Configuration conf)
+ throws IOException {
+ Path p = getPath(configUri);
+ FileSystem fs = p.getFileSystem(conf);
+ p = fs.resolvePath(p.makeQualified(fs.getUri(), fs.getWorkingDirectory()));
+ FileSystem targetFS = p.getFileSystem(conf);
+ return targetFS.listFiles(p, false);
+ }
+
+ private static Path getPath(String configUri) {
try {
- uri = new URI(fileName);
+ return new Path(new URI(configUri));
} catch (URISyntaxException e) {
- String message = "Invalid URI defined in configuration for"
- + " location of TEZ jars. providedURI=" + fileName;
+ String message = "Invalid URI defined in configuration for" + " location of TEZ jars. providedURI=" + configUri;
LOG.error(message);
throw new TezUncheckedException(message, e);
}
-
- Path p = new Path(uri);
- FileSystem fs = p.getFileSystem(conf);
- p = fs.resolvePath(p.makeQualified(fs.getUri(),
- fs.getWorkingDirectory()));
- FileSystem targetFS = p.getFileSystem(conf);
- if (targetFS.isDirectory(p)) {
- return targetFS.listStatus(p);
- } else {
- FileStatus fStatus = targetFS.getFileStatus(p);
- return new FileStatus[]{fStatus};
- }
}
/**
* Setup LocalResource map for Tez jars based on provided Configuration
- *
+ *
* @param conf
* Configuration to use to access Tez jars' locations
* @param credentials
@@ -160,11 +160,11 @@ private static FileStatus[] getLRFileStatus(String fileName, Configuration conf)
static boolean setupTezJarsLocalResources(TezConfiguration conf,
Credentials credentials, Map tezJarResources)
throws IOException {
- Preconditions.checkNotNull(credentials, "A non-null credentials object should be specified");
+ Objects.requireNonNull(credentials, "A non-null credentials object should be specified");
boolean usingTezArchive = false;
if (conf.getBoolean(TezConfiguration.TEZ_IGNORE_LIB_URIS, false)){
- LOG.info("Ignoring '" + TezConfiguration.TEZ_LIB_URIS + "' since '" +
+ LOG.info("Ignoring '" + TezConfiguration.TEZ_LIB_URIS + "' since '" +
TezConfiguration.TEZ_IGNORE_LIB_URIS + "' is set to true");
} else {
// Add tez jars to local resource
@@ -230,15 +230,11 @@ private static boolean addLocalResources(Configuration conf,
} else {
type = LocalResourceType.FILE;
}
+ RemoteIterator fileStatuses = getListFilesFileStatus(configUri, conf);
- FileStatus [] fileStatuses = getLRFileStatus(configUri, conf);
-
- for (FileStatus fStatus : fileStatuses) {
+ while (fileStatuses.hasNext()) {
+ LocatedFileStatus fStatus = fileStatuses.next();
String linkName;
- if (fStatus.isDirectory()) {
- // Skip directories - no recursive search support.
- continue;
- }
// If the resource is an archive, we've already done this work
if(type != LocalResourceType.ARCHIVE) {
u = fStatus.getPath().toUri();
@@ -247,8 +243,7 @@ private static boolean addLocalResources(Configuration conf,
p = remoteFS.resolvePath(p.makeQualified(remoteFS.getUri(),
remoteFS.getWorkingDirectory()));
if(null != u.getFragment()) {
- LOG.warn("Fragment set for link being interpreted as a file," +
- "URI: " + u.toString());
+ LOG.warn("Fragment set for link being interpreted as a file, URI: {}", u);
}
}
@@ -321,7 +316,7 @@ static void processTezLocalCredentialsFile(Credentials credentials, Configuratio
/**
* Verify or create the Staging area directory on the configured Filesystem
* @param stagingArea Staging area directory path
- * @return the FileSytem for the staging area directory
+ * @return the FileSystem for the staging area directory
* @throws IOException
*/
public static FileSystem ensureStagingDirExists(Configuration conf,
@@ -333,8 +328,13 @@ public static FileSystem ensureStagingDirExists(Configuration conf,
UserGroupInformation ugi = UserGroupInformation.getLoginUser();
realUser = ugi.getShortUserName();
currentUser = UserGroupInformation.getCurrentUser().getShortUserName();
- if (fs.exists(stagingArea)) {
- FileStatus fsStatus = fs.getFileStatus(stagingArea);
+ FileStatus fsStatus = null;
+ try {
+ fsStatus = fs.getFileStatus(stagingArea);
+ } catch (FileNotFoundException fnf) {
+ // Ignore
+ }
+ if (fsStatus != null) {
String owner = fsStatus.getOwner();
if (!(owner.equals(currentUser) || owner.equals(realUser))) {
throw new IOException("The ownership on the staging directory "
@@ -354,7 +354,7 @@ public static FileSystem ensureStagingDirExists(Configuration conf,
}
return fs;
}
-
+
/**
* Populate {@link Credentials} for the URI's to access them from their {@link FileSystem}s
* @param uris URIs that need to be accessed
@@ -382,7 +382,7 @@ public Path apply(URI input) {
* Obtains tokens for the DAG based on the list of URIs setup in the DAG. The
* fetched credentials are populated back into the DAG and can be retrieved
* via dag.getCredentials
- *
+ *
* @param dag
* the dag for which credentials need to be setup
* @param sessionCredentials
@@ -395,15 +395,14 @@ public Path apply(URI input) {
static Credentials setupDAGCredentials(DAG dag, Credentials sessionCredentials,
Configuration conf) throws IOException {
- Preconditions.checkNotNull(sessionCredentials);
+ Objects.requireNonNull(sessionCredentials);
TezCommonUtils.logCredentials(LOG, sessionCredentials, "session");
-
Credentials dagCredentials = new Credentials();
// All session creds are required for the DAG.
dagCredentials.mergeAll(sessionCredentials);
-
+
// Add additional credentials based on any URIs that the user may have specified.
-
+
// Obtain Credentials for any paths that the user may have configured.
addFileSystemCredentialsFromURIs(dag.getURIsForCredentials(), dagCredentials, conf);
@@ -423,7 +422,7 @@ static Credentials setupDAGCredentials(DAG dag, Credentials sessionCredentials,
addFileSystemCredentialsFromURIs(dataSink.getURIsForCredentials(), dagCredentials, conf);
}
}
-
+
for (LocalResource lr: dag.getTaskLocalFiles().values()) {
lrPaths.add(ConverterUtils.getPathFromYarnURL(lr.getResource()));
}
@@ -434,7 +433,7 @@ static Credentials setupDAGCredentials(DAG dag, Credentials sessionCredentials,
} catch (URISyntaxException e) {
throw new IOException(e);
}
-
+
return dagCredentials;
}
@@ -461,7 +460,7 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
ServicePluginsDescriptor servicePluginsDescriptor, JavaOptsChecker javaOptsChecker)
throws IOException, YarnException {
- Preconditions.checkNotNull(sessionCreds);
+ Objects.requireNonNull(sessionCreds);
TezConfiguration conf = amConfig.getTezConfiguration();
FileSystem fs = TezClientUtils.ensureStagingDirExists(conf,
@@ -479,24 +478,13 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
capability.setVirtualCores(
amConfig.getTezConfiguration().getInt(TezConfiguration.TEZ_AM_RESOURCE_CPU_VCORES,
TezConfiguration.TEZ_AM_RESOURCE_CPU_VCORES_DEFAULT));
- if (LOG.isDebugEnabled()) {
- LOG.debug("AppMaster capability = " + capability);
- }
+ LOG.debug("AppMaster capability = {}", capability);
// Setup required Credentials for the AM launch. DAG specific credentials
// are handled separately.
ByteBuffer securityTokens = null;
- // Setup security tokens
- Credentials amLaunchCredentials = new Credentials();
- if (amConfig.getCredentials() != null) {
- amLaunchCredentials.addAll(amConfig.getCredentials());
- }
-
- // Add Staging dir creds to the list of session credentials.
- TokenCache.obtainTokensForFileSystems(sessionCreds, new Path[]{binaryConfPath}, conf);
-
- // Add session specific credentials to the AM credentials.
- amLaunchCredentials.mergeAll(sessionCreds);
+ Credentials amLaunchCredentials =
+ prepareAmLaunchCredentials(amConfig, sessionCreds, conf, binaryConfPath);
DataOutputBuffer dob = new DataOutputBuffer();
amLaunchCredentials.writeTokenStorageToStream(dob);
@@ -515,7 +503,7 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
String[] amLogParams = parseLogParams(amLogLevelString);
String amLogLevel = amLogParams[0];
- maybeAddDefaultLoggingJavaOpts(amLogLevel, vargs);
+ TezClientUtils.addLog4jSystemProperties(amLogLevel, vargs);
// FIX sun bug mentioned in TEZ-327
@@ -540,10 +528,7 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
}
vargsFinal.add(mergedCommand.toString());
- if (LOG.isDebugEnabled()) {
- LOG.debug("Command to launch container for ApplicationMaster is : "
- + mergedCommand);
- }
+ LOG.debug("Command to launch container for ApplicationMaster is : {}", mergedCommand);
Map environment = new TreeMap();
TezYARNUtils.setupDefaultEnv(environment, conf,
@@ -575,16 +560,19 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
}
// emit conf as PB file
- ConfigurationProto finalConfProto = createFinalConfProtoForApp(tezConf,
- servicePluginsDescriptor);
+ // don't overwrite existing conf, needed for TezClient.getClient() so existing containers have stable resource fingerprints
+ if(!binaryConfPath.getFileSystem(tezConf).exists(binaryConfPath)) {
+ ConfigurationProto finalConfProto = createFinalConfProtoForApp(tezConf,
+ servicePluginsDescriptor);
- FSDataOutputStream amConfPBOutBinaryStream = null;
- try {
- amConfPBOutBinaryStream = TezCommonUtils.createFileForAM(fs, binaryConfPath);
- finalConfProto.writeTo(amConfPBOutBinaryStream);
- } finally {
- if(amConfPBOutBinaryStream != null){
- amConfPBOutBinaryStream.close();
+ FSDataOutputStream amConfPBOutBinaryStream = null;
+ try {
+ amConfPBOutBinaryStream = TezCommonUtils.createFileForAM(fs, binaryConfPath);
+ finalConfProto.writeTo(amConfPBOutBinaryStream);
+ } finally {
+ if (amConfPBOutBinaryStream != null) {
+ amConfPBOutBinaryStream.close();
+ }
}
}
@@ -606,7 +594,7 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
if (amLocalResources != null && !amLocalResources.isEmpty()) {
amResourceProto = DagTypeConverters.convertFromLocalResources(amLocalResources);
} else {
- amResourceProto = DAGProtos.PlanLocalResourcesProto.getDefaultInstance();
+ amResourceProto = DAGProtos.PlanLocalResourcesProto.getDefaultInstance();
}
amResourceProto.writeDelimitedTo(sessionJarsPBOutStream);
} finally {
@@ -628,7 +616,7 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
Map acls = aclManager.toYARNACls();
if(dag != null) {
-
+
DAGPlan dagPB = prepareAndCreateDAGPlan(dag, amConfig, tezJarResources, tezLrsAsArchive,
sessionCreds, servicePluginsDescriptor, javaOptsChecker);
@@ -713,38 +701,72 @@ public static ApplicationSubmissionContext createApplicationSubmissionContext(
return appContext;
}
-
+
+ static Credentials prepareAmLaunchCredentials(AMConfiguration amConfig, Credentials sessionCreds,
+ TezConfiguration conf, Path binaryConfPath) throws IOException {
+ // Setup security tokens
+ Credentials amLaunchCredentials = new Credentials();
+
+ // Add SimpleHistoryLoggingService logDir creds to the list of session credentials
+ // If it is on HDFS
+ String simpleHistoryLogDir = conf.get(TezConfiguration.TEZ_SIMPLE_HISTORY_LOGGING_DIR);
+ if (simpleHistoryLogDir != null && !simpleHistoryLogDir.isEmpty()) {
+ Path simpleHistoryLogDirPath = new Path(simpleHistoryLogDir);
+ TokenCache.obtainTokensForFileSystems(sessionCreds, new Path[] { simpleHistoryLogDirPath },
+ conf);
+ }
+
+ // Add Staging dir creds to the list of session credentials.
+ TokenCache.obtainTokensForFileSystems(sessionCreds, new Path[] {binaryConfPath }, conf);
+
+ populateTokenCache(conf, sessionCreds);
+
+ // Add session specific credentials to the AM credentials.
+ amLaunchCredentials.mergeAll(sessionCreds);
+
+ if (amConfig.getCredentials() != null) {
+ amLaunchCredentials.mergeAll(amConfig.getCredentials());
+ }
+ TezCommonUtils.logCredentials(LOG, amLaunchCredentials, "amLaunch");
+ return amLaunchCredentials;
+ }
+
+ //get secret keys and tokens and store them into TokenCache
+ private static void populateTokenCache(TezConfiguration conf, Credentials credentials)
+ throws IOException{
+ // add the delegation tokens from configuration
+ String[] nameNodes = conf.getStrings(TezConfiguration.TEZ_JOB_FS_SERVERS);
+ LOG.debug("adding the following namenodes' delegation tokens:" +
+ Arrays.toString(nameNodes));
+ if(nameNodes != null) {
+ Path[] ps = new Path[nameNodes.length];
+ for(int i = 0; i < nameNodes.length; i++) {
+ ps[i] = new Path(nameNodes[i]);
+ }
+ TokenCache.obtainTokensForFileSystems(credentials, ps, conf);
+ }
+ }
+
static DAGPlan prepareAndCreateDAGPlan(DAG dag, AMConfiguration amConfig,
Map tezJarResources, boolean tezLrsAsArchive,
Credentials credentials, ServicePluginsDescriptor servicePluginsDescriptor,
JavaOptsChecker javaOptsChecker) throws IOException {
Credentials dagCredentials = setupDAGCredentials(dag, credentials,
amConfig.getTezConfiguration());
+ TezCommonUtils.logCredentials(LOG, dagCredentials, "dagPlan");
return dag.createDag(amConfig.getTezConfiguration(), dagCredentials, tezJarResources,
amConfig.getBinaryConfLR(), tezLrsAsArchive, servicePluginsDescriptor, javaOptsChecker);
}
-
- static void maybeAddDefaultLoggingJavaOpts(String logLevel, List vargs) {
- Preconditions.checkNotNull(vargs);
- if (!vargs.isEmpty()) {
- for (String arg : vargs) {
- if (arg.contains(TezConstants.TEZ_ROOT_LOGGER_NAME)) {
- return;
- }
- }
- }
- TezClientUtils.addLog4jSystemProperties(logLevel, vargs);
- }
@Private
public static String maybeAddDefaultLoggingJavaOpts(String logLevel, String javaOpts) {
List vargs = new ArrayList(5);
if (javaOpts != null) {
- vargs.add(javaOpts);
+ Collections.addAll(vargs, javaOpts.split(" "));
} else {
vargs.add("");
}
- maybeAddDefaultLoggingJavaOpts(logLevel, vargs);
+ TezClientUtils.addLog4jSystemProperties(logLevel, vargs);
if (vargs.size() == 1) {
return vargs.get(0);
}
@@ -790,13 +812,25 @@ public static String addDefaultsToTaskLaunchCmdOpts(String vOpts, Configuration
@VisibleForTesting
public static void addLog4jSystemProperties(String logLevel,
List vargs) {
+ Objects.requireNonNull(vargs);
vargs.add("-Dlog4j.configuratorClass=org.apache.tez.common.TezLog4jConfigurator");
vargs.add("-Dlog4j.configuration="
+ TezConstants.TEZ_CONTAINER_LOG4J_PROPERTIES_FILE);
vargs.add("-D" + YarnConfiguration.YARN_APP_CONTAINER_LOG_DIR + "="
+ ApplicationConstants.LOG_DIR_EXPANSION_VAR);
- vargs.add("-D" + TezConstants.TEZ_ROOT_LOGGER_NAME + "=" + logLevel
- + "," + TezConstants.TEZ_CONTAINER_LOGGER_NAME);
+ boolean isRootLoggerPresent = false;
+ String rootLoggerArg = "-D" + TezConstants.TEZ_ROOT_LOGGER_NAME + "=" + logLevel
+ + "," + TezConstants.TEZ_CONTAINER_LOGGER_NAME;
+ for (int i = 0; i < vargs.size(); i++) {
+ String arg = vargs.get(i);
+ if (arg.contains(TezConstants.TEZ_ROOT_LOGGER_NAME)) {
+ vargs.set(i, rootLoggerArg);
+ isRootLoggerPresent = true;
+ }
+ }
+ if (!isRootLoggerPresent) {
+ vargs.add(rootLoggerArg);
+ }
}
static ConfigurationProto createFinalConfProtoForApp(Configuration amConf,
@@ -804,10 +838,16 @@ static ConfigurationProto createFinalConfProtoForApp(Configuration amConf,
assert amConf != null;
ConfigurationProto.Builder builder = ConfigurationProto.newBuilder();
for (Entry entry : amConf) {
- PlanKeyValuePair.Builder kvp = PlanKeyValuePair.newBuilder();
- kvp.setKey(entry.getKey());
- kvp.setValue(amConf.get(entry.getKey()));
- builder.addConfKeyValues(kvp);
+ String key = entry.getKey();
+ String val = amConf.get(key);
+ if(val != null) {
+ PlanKeyValuePair.Builder kvp = PlanKeyValuePair.newBuilder();
+ kvp.setKey(key);
+ kvp.setValue(val);
+ builder.addConfKeyValues(kvp);
+ } else {
+ LOG.debug("null value in Configuration after replacement for key={}. Skipping.", key);
+ }
}
AMPluginDescriptorProto pluginDescriptorProto =
@@ -871,13 +911,12 @@ private static Path localizeDagPlanAsText(DAGPlan dagPB, FileSystem fs, AMConfig
return textPath;
}
- static DAGClientAMProtocolBlockingPB getAMProxy(FrameworkClient yarnClient,
- Configuration conf,
- ApplicationId applicationId) throws TezException, IOException {
+ static DAGClientAMProtocolBlockingPB getAMProxy(FrameworkClient frameworkClient,
+ Configuration conf, ApplicationId applicationId, UserGroupInformation ugi)
+ throws TezException, IOException {
ApplicationReport appReport;
try {
- appReport = yarnClient.getApplicationReport(
- applicationId);
+ appReport = frameworkClient.getApplicationReport(applicationId);
if(appReport == null) {
throw new TezUncheckedException("Could not retrieve application report"
@@ -907,25 +946,23 @@ static DAGClientAMProtocolBlockingPB getAMProxy(FrameworkClient yarnClient,
} catch (YarnException e) {
throw new TezException(e);
}
- return getAMProxy(conf, appReport.getHost(),
- appReport.getRpcPort(), appReport.getClientToAMToken());
+
+ return getAMProxy(conf, appReport.getHost(), appReport.getRpcPort(),
+ appReport.getClientToAMToken(), ugi);
}
@Private
public static DAGClientAMProtocolBlockingPB getAMProxy(final Configuration conf, String amHost,
- int amRpcPort, org.apache.hadoop.yarn.api.records.Token clientToAMToken) throws IOException {
+ int amRpcPort, org.apache.hadoop.yarn.api.records.Token clientToAMToken,
+ UserGroupInformation userUgi) throws IOException {
final InetSocketAddress serviceAddr = NetUtils.createSocketAddrForHost(amHost, amRpcPort);
- UserGroupInformation userUgi = UserGroupInformation.createRemoteUser(UserGroupInformation
- .getCurrentUser().getUserName());
if (clientToAMToken != null) {
Token token = ConverterUtils.convertFromYarn(clientToAMToken,
serviceAddr);
userUgi.addToken(token);
}
- if (LOG.isDebugEnabled()) {
- LOG.debug("Connecting to Tez AM at " + serviceAddr);
- }
+ LOG.debug("Connecting to Tez AM at {}", serviceAddr);
DAGClientAMProtocolBlockingPB proxy = null;
try {
proxy = userUgi.doAs(new PrivilegedExceptionAction() {
@@ -969,11 +1006,11 @@ public static String maybeAddDefaultMemoryJavaOpts(String javaOpts, Resource res
return javaOpts;
}
- if ((maxHeapFactor <= 0 && !Precision.equals(maxHeapFactor, -1, 0.01)) || maxHeapFactor >= 1) {
+ if ((maxHeapFactor <= 0 && Double.valueOf("-1") != maxHeapFactor) || maxHeapFactor >= 1) {
return javaOpts;
}
- if (Precision.equals(maxHeapFactor, -1, 0.01)) {
+ if (Double.valueOf("-1") == maxHeapFactor) {
maxHeapFactor = resource.getMemory() < TezConstants.TEZ_CONTAINER_SMALL_SLAB_BOUND_MB
? TezConstants.TEZ_CONTAINER_MAX_JAVA_HEAP_FRACTION_SMALL_SLAB
: TezConstants.TEZ_CONTAINER_MAX_JAVA_HEAP_FRACTION_LARGE_SLAB;
@@ -1075,7 +1112,7 @@ public static void setApplicationPriority(ApplicationSubmissionContext context,
int priority = amConfig.getTezConfiguration().getInt(TezConfiguration.TEZ_AM_APPLICATION_PRIORITY, 0);
context.setPriority(Priority.newInstance(priority));
if (LOG.isDebugEnabled()) {
- LOG.debug("Settting TEZ application priority, applicationId= " + context.getApplicationId() +
+ LOG.debug("Setting TEZ application priority, applicationId= " + context.getApplicationId() +
", priority= " + context.getPriority().getPriority());
}
}
@@ -1086,7 +1123,7 @@ public static byte[] getLocalSha(Path path, Configuration conf) throws IOExcepti
InputStream is = null;
try {
is = FileSystem.getLocal(conf).open(path);
- return DigestUtils.sha256(is);
+ return DigestUtils.sha384(is);
} finally {
if (is != null) {
is.close();
@@ -1098,7 +1135,7 @@ public static byte[] getResourceSha(URI uri, Configuration conf) throws IOExcept
InputStream is = null;
try {
is = FileSystem.get(uri, conf).open(new Path(uri));
- return DigestUtils.sha256(is);
+ return DigestUtils.sha384(is);
} finally {
if (is != null) {
is.close();
diff --git a/tez-api/src/main/java/org/apache/tez/client/TezYarnClient.java b/tez-api/src/main/java/org/apache/tez/client/TezYarnClient.java
index 2a0c79ab65..d109648075 100644
--- a/tez-api/src/main/java/org/apache/tez/client/TezYarnClient.java
+++ b/tez-api/src/main/java/org/apache/tez/client/TezYarnClient.java
@@ -40,13 +40,16 @@ public class TezYarnClient extends FrameworkClient {
private volatile boolean isRunning;
+ private String amHost;
+ private int amPort;
+
protected TezYarnClient(YarnClient yarnClient) {
this.yarnClient = yarnClient;
}
@Override
- public void init(TezConfiguration tezConf, YarnConfiguration yarnConf) {
- yarnClient.init(yarnConf);
+ public void init(TezConfiguration tezConf) {
+ yarnClient.init(new YarnConfiguration(tezConf));
}
@Override
@@ -100,6 +103,8 @@ public ApplicationReport getApplicationReport(ApplicationId appId) throws YarnEx
throw new ApplicationNotFoundException("YARN reports no state for application "
+ appId);
}
+ this.amHost = report.getHost();
+ this.amPort = report.getRpcPort();
return report;
}
@@ -107,4 +112,14 @@ public ApplicationReport getApplicationReport(ApplicationId appId) throws YarnEx
public boolean isRunning() throws IOException {
return isRunning;
}
+
+ @Override
+ public String getAmHost() {
+ return amHost;
+ }
+
+ @Override
+ public int getAmPort() {
+ return amPort;
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/ATSConstants.java b/tez-api/src/main/java/org/apache/tez/common/ATSConstants.java
index 6e07849341..e3c90d3154 100644
--- a/tez-api/src/main/java/org/apache/tez/common/ATSConstants.java
+++ b/tez-api/src/main/java/org/apache/tez/common/ATSConstants.java
@@ -107,6 +107,10 @@ public class ATSConstants {
public static final String COUNTER_NAME = "counterName";
public static final String COUNTER_DISPLAY_NAME = "counterDisplayName";
public static final String COUNTER_VALUE = "counterValue";
+ public static final String COUNTER_MIN_VALUE = "counterMinValue";
+ public static final String COUNTER_MAX_VALUE = "counterMaxValue";
+ public static final String COUNTER_INSTANCE_COUNT = "counterInstanceCount";
+
/* Url related */
public static final String RESOURCE_URI_BASE = "/ws/v1/timeline";
@@ -134,4 +138,5 @@ public class ATSConstants {
public static final String CALLER_TYPE = "callerType";
public static final String DESCRIPTION = "description";
+ protected ATSConstants() {}
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/CachedEntity.java b/tez-api/src/main/java/org/apache/tez/common/CachedEntity.java
new file mode 100644
index 0000000000..47ccd77e48
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/CachedEntity.java
@@ -0,0 +1,104 @@
+/**
+ * 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.tez.common;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.hadoop.yarn.util.Clock;
+import org.apache.hadoop.yarn.util.MonotonicClock;
+
+/**
+ * A thread safe implementation used as a container for cacheable entries with Expiration times.
+ * It supports custom {@link Clock} to control the elapsed time calculation.
+ * @param the data object type.
+ */
+public class CachedEntity {
+ private final AtomicReference entryDataRef;
+ private final Clock cacheClock;
+ private final long expiryDurationMS;
+ private volatile long entryTimeStamp;
+
+ public CachedEntity(TimeUnit expiryTimeUnit, long expiryLength, Clock clock) {
+ entryDataRef = new AtomicReference<>(null);
+ cacheClock = clock;
+ expiryDurationMS = TimeUnit.MILLISECONDS.convert(expiryLength, expiryTimeUnit);
+ entryTimeStamp = 0;
+ }
+
+ public CachedEntity(TimeUnit expiryTimeUnit, long expiryLength) {
+ this(expiryTimeUnit, expiryLength, new MonotonicClock());
+ }
+
+ /**
+ *
+ * @return true if expiration timestamp is 0, or the elapsed time since last update is
+ * greater than {@link #expiryDurationMS}
+ */
+ public boolean isExpired() {
+ return (entryTimeStamp == 0)
+ || ((cacheClock.getTime() - entryTimeStamp) > expiryDurationMS);
+ }
+
+ /**
+ * If the entry has expired, it reset the cache reference through {@link #clearExpiredEntry()}.
+ * @return cached data if the timestamp is valid. Null, if the timestamp has expired.
+ */
+ public T getValue() {
+ if (isExpired()) { // quick check for expiration
+ if (clearExpiredEntry()) { // remove reference to the expired entry
+ return null;
+ }
+ }
+ return entryDataRef.get();
+ }
+
+ /**
+ * Safely sets the cached data.
+ * @param newEntry
+ */
+ public void setValue(T newEntry) {
+ T currentEntry = entryDataRef.get();
+ while (!entryDataRef.compareAndSet(currentEntry, newEntry)) {
+ currentEntry = entryDataRef.get();
+ }
+ entryTimeStamp = cacheClock.getTime();
+ }
+
+ /**
+ * Enforces the expiration of the cached entry.
+ */
+ public void enforceExpiration() {
+ entryTimeStamp = 0;
+ }
+
+ /**
+ * Safely deletes the reference to the data if it was not null.
+ * @return true if the reference is set to Null. False indicates that another thread
+ * updated the cache.
+ */
+ private boolean clearExpiredEntry() {
+ T currentEntry = entryDataRef.get();
+ if (currentEntry == null) {
+ return true;
+ }
+ // the current value is not null: try to reset it.
+ // if the CAS is successful, then we won't override a recent update to the cache.
+ return (entryDataRef.compareAndSet(currentEntry, null));
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/GuavaShim.java b/tez-api/src/main/java/org/apache/tez/common/GuavaShim.java
new file mode 100644
index 0000000000..d9b8796d61
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/GuavaShim.java
@@ -0,0 +1,54 @@
+/**
+ * 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.tez.common;
+
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+
+/**
+ * A interoperability layer to work with multiple versions of guava.
+ */
+public final class GuavaShim {
+
+ static {
+ try {
+ executorMethod = MoreExecutors.class.getDeclaredMethod("directExecutor");
+ } catch (NoSuchMethodException nsme) {
+ try {
+ executorMethod = MoreExecutors.class.getDeclaredMethod("sameThreadExecutor");
+ } catch (NoSuchMethodException nsmeSame) {
+ }
+ }
+ }
+
+ private GuavaShim() {
+ }
+
+ private static Method executorMethod;
+
+ public static Executor directExecutor() {
+ try {
+ return (Executor) executorMethod.invoke(null);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tez-api/src/main/java/org/apache/tez/common/JavaOptsChecker.java b/tez-api/src/main/java/org/apache/tez/common/JavaOptsChecker.java
index 6de402aae9..3e93446149 100644
--- a/tez-api/src/main/java/org/apache/tez/common/JavaOptsChecker.java
+++ b/tez-api/src/main/java/org/apache/tez/common/JavaOptsChecker.java
@@ -38,9 +38,8 @@ public class JavaOptsChecker {
public void checkOpts(String opts) throws TezException {
Set gcOpts = new TreeSet();
- if (LOG.isDebugEnabled()) {
- LOG.debug("Checking JVM GC opts: " + opts);
- }
+ LOG.debug("Checking JVM GC opts: {}", opts);
+
Matcher matcher = pattern.matcher(opts);
while (matcher.find()) {
if (matcher.groupCount() != 3) {
@@ -74,10 +73,8 @@ public void checkOpts(String opts) throws TezException {
}
}
- if (LOG.isDebugEnabled()) {
- LOG.debug("Found clashing GC opts"
- + ", conflicting GC Values=" + gcOpts);
- }
+ LOG.debug("Found clashing GC opts, conflicting GC Values={}", gcOpts);
+
throw new TezException("Invalid/conflicting GC options found,"
+ " cmdOpts=\"" + opts + "\"");
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/Preconditions.java b/tez-api/src/main/java/org/apache/tez/common/Preconditions.java
new file mode 100644
index 0000000000..b32d951101
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/Preconditions.java
@@ -0,0 +1,115 @@
+/**
+ * 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.tez.common;
+
+import javax.annotation.Nullable;
+
+/**
+ * A simplified version of Guava's Preconditions for making it easy to handle its usage in Tez project.
+ */
+//TODO remove this and make Preconditions class in common module available everywhere
+public class Preconditions {
+
+ private Preconditions() {
+ }
+
+ public static void checkArgument(boolean expression) {
+ if (!expression) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void checkArgument(boolean expression, @Nullable Object message) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.valueOf(message));
+ }
+ }
+
+ public static void checkArgument(boolean expression, @Nullable String template, @Nullable Object... args) {
+ if (!expression) {
+ throw new IllegalArgumentException(format(template, args));
+ }
+ }
+
+ public static void checkState(boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ public static void checkState(boolean expression, @Nullable Object message) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(message));
+ }
+ }
+
+ public static void checkState(boolean expression, @Nullable String template, @Nullable Object... args) {
+ if (!expression) {
+ throw new IllegalStateException(format(template, args));
+ }
+ }
+
+ private static String format(@Nullable String template, @Nullable Object... args) {
+ template = String.valueOf(template); // null -> "null"
+
+ if (args == null) {
+ args = new Object[] { "(Object[])null" };
+ } else {
+ for (int i = 0; i < args.length; i++) {
+ args[i] = lenientToString(args[i]);
+ }
+ }
+
+ // start substituting the arguments into the '%s' placeholders
+ StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
+ int templateStart = 0;
+ int i = 0;
+ while (i < args.length) {
+ int placeholderStart = template.indexOf("%s", templateStart);
+ if (placeholderStart == -1) {
+ break;
+ }
+ builder.append(template, templateStart, placeholderStart);
+ builder.append(args[i++]);
+ templateStart = placeholderStart + 2;
+ }
+ builder.append(template, templateStart, template.length());
+
+ // if we run out of placeholders, append the extra args in square braces
+ if (i < args.length) {
+ builder.append(" [");
+ builder.append(args[i++]);
+ while (i < args.length) {
+ builder.append(", ");
+ builder.append(args[i++]);
+ }
+ builder.append(']');
+ }
+
+ return builder.toString();
+ }
+
+ private static String lenientToString(@Nullable Object o) {
+ try {
+ return String.valueOf(o);
+ } catch (Exception e) {
+ String objectToString = o.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(o));
+ return "<" + objectToString + " threw " + e.getClass().getName() + ">";
+ }
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/ProgressHelper.java b/tez-api/src/main/java/org/apache/tez/common/ProgressHelper.java
index 407a20e299..289847a96a 100644
--- a/tez-api/src/main/java/org/apache/tez/common/ProgressHelper.java
+++ b/tez-api/src/main/java/org/apache/tez/common/ProgressHelper.java
@@ -19,71 +19,151 @@
package org.apache.tez.common;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.tez.runtime.api.AbstractLogicalInput;
import org.apache.tez.runtime.api.LogicalInput;
import org.apache.tez.runtime.api.ProcessorContext;
-import org.apache.tez.runtime.api.ProgressFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ProgressHelper {
- private static final Logger LOG = LoggerFactory.getLogger(ProgressHelper.class);
- private String processorName;
+ private static final Logger LOG =
+ LoggerFactory.getLogger(ProgressHelper.class);
+ private static final float MIN_PROGRESS_VAL = 0.0f;
+ private static final float MAX_PROGRESS_VAL = 1.0f;
+ private final String processorName;
protected final Map inputs;
- final ProcessorContext processorContext;
+ private final ProcessorContext processorContext;
+ private final AtomicReference> periodicMonitorTaskRef;
+ private long monitorExecPeriod;
+ private volatile ScheduledExecutorService scheduledExecutorService;
- volatile ScheduledExecutorService scheduledExecutorService;
- Runnable monitorProgress = new Runnable() {
- @Override
- public void run() {
- try {
- float progSum = 0.0f;
- float progress;
- if (inputs != null && inputs.size() != 0) {
- for (LogicalInput input : inputs.values()) {
- if (input instanceof AbstractLogicalInput) {
- progSum += ((AbstractLogicalInput) input).getProgress();
+ public static final float processProgress(float val) {
+ return (Float.isNaN(val)) ? MIN_PROGRESS_VAL
+ : Math.max(MIN_PROGRESS_VAL, Math.min(MAX_PROGRESS_VAL, val));
+ }
+
+ public static final boolean isProgressWithinRange(float val) {
+ return (val <= MAX_PROGRESS_VAL && val >= MIN_PROGRESS_VAL);
+ }
+
+ public ProgressHelper(Map inputsParam,
+ ProcessorContext context, String processorName) {
+ this.periodicMonitorTaskRef = new AtomicReference<>(null);
+ this.inputs = inputsParam;
+ this.processorContext = context;
+ this.processorName = processorName;
+ }
+
+ public void scheduleProgressTaskService(long delay, long period) {
+ monitorExecPeriod = period;
+ scheduledExecutorService =
+ Executors.newScheduledThreadPool(1,
+ new ThreadFactoryBuilder().setDaemon(true).setNameFormat(
+ "TaskProgressService{" + processorName + ":" + processorContext
+ .getTaskVertexName()
+ + "} #%d").build());
+ try {
+ createPeriodicTask(delay);
+ } catch (RejectedExecutionException | IllegalArgumentException ex) {
+ LOG.error("Could not create periodic scheduled task for processor={}",
+ processorName, ex);
+ }
+ }
+
+ private Runnable createRunnableMonitor() {
+ return new Runnable() {
+ @Override
+ public void run() {
+ try {
+ float progSum = MIN_PROGRESS_VAL;
+ int invalidInput = 0;
+ float progressVal = MIN_PROGRESS_VAL;
+ if (inputs != null && !inputs.isEmpty()) {
+ for (LogicalInput input : inputs.values()) {
+ if (!(input instanceof AbstractLogicalInput)) {
+ /**
+ * According to javdoc in
+ * {@link org.apache.tez.runtime.api.AbstractLogicalInput} all
+ * implementations must extend AbstractLogicalInput.
+ */
+ continue;
+ }
+ final float inputProgress =
+ ((AbstractLogicalInput) input).getProgress();
+ if (!isProgressWithinRange(inputProgress)) {
+ final int invalidSnapshot = ++invalidInput;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "progress update: Incorrect value in progress helper in "
+ + "processor={}, inputProgress={}, inputsSize={}, "
+ + "invalidInput={}",
+ processorName, inputProgress, inputs.size(),
+ invalidSnapshot);
+ }
+ }
+ progSum += processProgress(inputProgress);
}
+ // No need to process the average within the valid range since the
+ // processorContext validates the value before being set.
+ progressVal = progSum / inputs.size();
+ }
+ // Report progress as 0.0f when if are errors.
+ processorContext.setProgress(progressVal);
+ } catch (Throwable th) {
+ LOG.debug("progress update: Encountered InterruptedException during"
+ + " Processor={}", processorName, th);
+ if (th instanceof InterruptedException) {
+ // set interrupt flag to true sand exit
+ Thread.currentThread().interrupt();
+ return;
}
- progress = (1.0f) * progSum / inputs.size();
- } else {
- progress = 1.0f;
}
- processorContext.setProgress(progress);
- } catch (ProgressFailedException pe) {
- LOG.warn("Encountered ProgressFailedException during Processor progress update"
- + pe);
- } catch (InterruptedException ie) {
- LOG.warn("Encountered InterruptedException during Processor progress update"
- + ie);
}
- }
- };
+ };
+ }
- public ProgressHelper(Map _inputs, ProcessorContext context, String processorName) {
- this.inputs = _inputs;
- this.processorContext = context;
- this.processorName = processorName;
+ private boolean createPeriodicTask(long delay)
+ throws RejectedExecutionException, IllegalArgumentException {
+ stopPeriodicMonitor();
+ final Runnable runnableMonitor = createRunnableMonitor();
+ ScheduledFuture> futureTask = scheduledExecutorService
+ .scheduleWithFixedDelay(runnableMonitor, delay, monitorExecPeriod,
+ TimeUnit.MILLISECONDS);
+ periodicMonitorTaskRef.set(futureTask);
+ return true;
}
- public void scheduleProgressTaskService(long delay, long period) {
- scheduledExecutorService = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder()
- .setDaemon(true).setNameFormat("TaskProgressService{" + processorName+ ":" + processorContext.getTaskVertexName()
- + "} #%d").build());
- scheduledExecutorService.scheduleWithFixedDelay(monitorProgress, delay, period,
- TimeUnit.MILLISECONDS);
+ private void stopPeriodicMonitor() {
+ ScheduledFuture> scheduledMonitorRes =
+ this.periodicMonitorTaskRef.get();
+ if (scheduledMonitorRes != null && !scheduledMonitorRes.isCancelled()) {
+ scheduledMonitorRes.cancel(true);
+ this.periodicMonitorTaskRef.set(null);
+ }
}
public void shutDownProgressTaskService() {
+ stopPeriodicMonitor();
if (scheduledExecutorService != null) {
+ scheduledExecutorService.shutdown();
+ try {
+ if (!scheduledExecutorService.awaitTermination(monitorExecPeriod,
+ TimeUnit.MILLISECONDS)) {
+ scheduledExecutorService.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ LOG.debug("Interrupted exception while shutting down the "
+ + "executor service for the processor name={}", processorName);
+ }
scheduledExecutorService.shutdownNow();
- scheduledExecutorService = null;
}
+ scheduledExecutorService = null;
}
-
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/RPCUtil.java b/tez-api/src/main/java/org/apache/tez/common/RPCUtil.java
index caeb822bc7..ab265f6ea8 100644
--- a/tez-api/src/main/java/org/apache/tez/common/RPCUtil.java
+++ b/tez-api/src/main/java/org/apache/tez/common/RPCUtil.java
@@ -24,12 +24,15 @@
import org.apache.hadoop.ipc.RemoteException;
import org.apache.tez.dag.api.DAGNotRunningException;
+import org.apache.tez.dag.api.NoCurrentDAGException;
import org.apache.tez.dag.api.SessionNotRunning;
import org.apache.tez.dag.api.TezException;
import com.google.protobuf.ServiceException;
-public class RPCUtil {
+public final class RPCUtil {
+
+ private RPCUtil() {}
/**
* Returns an instance of {@link TezException}
@@ -55,17 +58,8 @@ private static T instantiateException(
return ex;
// RemoteException contains useful information as against the
// java.lang.reflect exceptions.
- } catch (NoSuchMethodException e) {
- throw re;
- } catch (IllegalArgumentException e) {
- throw re;
- } catch (SecurityException e) {
- throw re;
- } catch (InstantiationException e) {
- throw re;
- } catch (IllegalAccessException e) {
- throw re;
- } catch (InvocationTargetException e) {
+ } catch (NoSuchMethodException | IllegalArgumentException | SecurityException | InstantiationException
+ | IllegalAccessException | InvocationTargetException e) {
throw re;
}
}
@@ -85,12 +79,6 @@ private static T instantiateRuntimeException(
return instantiateException(cls, re);
}
- private static T instantiateSessionNotRunningException(
- Class extends T> cls, RemoteException re) throws RemoteException {
- return instantiateException(cls, re);
- }
-
-
/**
* Utility method that unwraps and returns appropriate exceptions.
*
@@ -109,7 +97,7 @@ public static Void unwrapAndThrowException(ServiceException se)
} else {
if (cause instanceof RemoteException) {
RemoteException re = (RemoteException) cause;
- Class> realClass = null;
+ Class> realClass;
try {
realClass = Class.forName(re.getClassName());
} catch (ClassNotFoundException cnf) {
@@ -125,6 +113,9 @@ public static Void unwrapAndThrowException(ServiceException se)
} else if (DAGNotRunningException.class.isAssignableFrom(realClass)) {
throw instantiateTezException(
realClass.asSubclass(DAGNotRunningException.class), re);
+ } else if (NoCurrentDAGException.class.isAssignableFrom(realClass)) {
+ throw instantiateTezException(
+ realClass.asSubclass(NoCurrentDAGException.class), re);
} else if (TezException.class.isAssignableFrom(realClass)) {
throw instantiateTezException(
realClass.asSubclass(TezException.class), re);
diff --git a/tez-api/src/main/java/org/apache/tez/common/ReflectionUtils.java b/tez-api/src/main/java/org/apache/tez/common/ReflectionUtils.java
index 4d89ed4f9d..5bfb41c586 100644
--- a/tez-api/src/main/java/org/apache/tez/common/ReflectionUtils.java
+++ b/tez-api/src/main/java/org/apache/tez/common/ReflectionUtils.java
@@ -19,22 +19,21 @@
package org.apache.tez.common;
import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
-import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.tez.dag.api.TezReflectionException;
-import org.apache.tez.dag.api.TezUncheckedException;
@Private
-public class ReflectionUtils {
+public final class ReflectionUtils {
- private static final Map> CLAZZ_CACHE = new ConcurrentHashMap>();
+ private static final Map> CLAZZ_CACHE = new ConcurrentHashMap<>();
+
+ private ReflectionUtils() {}
@Private
public static Class> getClazz(String className) throws TezReflectionException {
@@ -109,43 +108,11 @@ public static Method getMethod(Class> targetClazz, String methodName, Class>
}
}
- @Private
- public static synchronized void addResourcesToClasspath(List urls) {
- ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), Thread
- .currentThread().getContextClassLoader());
- Thread.currentThread().setContextClassLoader(classLoader);
- }
-
- // Parameters for addResourcesToSystemClassLoader
- private static final Class>[] parameters = new Class[]{URL.class};
- private static Method sysClassLoaderMethod = null;
-
@Private
public static synchronized void addResourcesToSystemClassLoader(List urls) {
- URLClassLoader sysLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
- if (sysClassLoaderMethod == null) {
- Class> sysClass = URLClassLoader.class;
- Method method;
- try {
- method = sysClass.getDeclaredMethod("addURL", parameters);
- } catch (SecurityException e) {
- throw new TezUncheckedException("Failed to get handle on method addURL", e);
- } catch (NoSuchMethodException e) {
- throw new TezUncheckedException("Failed to get handle on method addURL", e);
- }
- method.setAccessible(true);
- sysClassLoaderMethod = method;
- }
+ TezClassLoader classLoader = TezClassLoader.getInstance();
for (URL url : urls) {
- try {
- sysClassLoaderMethod.invoke(sysLoader, new Object[] { url });
- } catch (IllegalArgumentException e) {
- throw new TezUncheckedException("Failed to invoke addURL for rsrc: " + url, e);
- } catch (IllegalAccessException e) {
- throw new TezUncheckedException("Failed to invoke addURL for rsrc: " + url, e);
- } catch (InvocationTargetException e) {
- throw new TezUncheckedException("Failed to invoke addURL for rsrc: " + url, e);
- }
+ classLoader.addURL(url);
}
}
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/TezClassLoader.java b/tez-api/src/main/java/org/apache/tez/common/TezClassLoader.java
new file mode 100644
index 0000000000..53c9e51fc6
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/TezClassLoader.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed 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.tez.common;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.hadoop.conf.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ClassLoader to allow addition of new paths to classpath in the runtime.
+ *
+ * It uses URLClassLoader with this class' classloader as parent classloader.
+ * And hence first delegates the resource loading to parent and then to the URLs
+ * added. The process must be setup to use by invoking setupTezClassLoader() which sets
+ * the global TezClassLoader as current thread context class loader. All threads
+ * created will inherit the classloader and hence will resolve the class/resource
+ * from TezClassLoader.
+ */
+public class TezClassLoader extends URLClassLoader {
+ private static final TezClassLoader INSTANCE;
+ private static final Logger LOG = LoggerFactory.getLogger(TezClassLoader.class);
+
+ static {
+ INSTANCE = AccessController.doPrivileged(new PrivilegedAction() {
+ public TezClassLoader run() {
+ return new TezClassLoader();
+ }
+ });
+ }
+
+ private TezClassLoader() {
+ super(new URL[] {}, TezClassLoader.class.getClassLoader());
+
+ LOG.info(
+ "Created TezClassLoader with parent classloader: {}, thread: {}, system classloader: {}",
+ TezClassLoader.class.getClassLoader(), Thread.currentThread().getId(),
+ ClassLoader.getSystemClassLoader());
+ }
+
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+
+ public static TezClassLoader getInstance() {
+ return INSTANCE;
+ }
+
+ public static void setupTezClassLoader() {
+ LOG.debug(
+ "Setting up TezClassLoader: thread: {}, current thread classloader: {} system classloader: {}",
+ Thread.currentThread().getId(), Thread.currentThread().getContextClassLoader(),
+ ClassLoader.getSystemClassLoader());
+ Thread.currentThread().setContextClassLoader(INSTANCE);
+ }
+
+ public static void setupForConfiguration(Configuration configuration) {
+ configuration.setClassLoader(INSTANCE);
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/TezCommonUtils.java b/tez-api/src/main/java/org/apache/tez/common/TezCommonUtils.java
index 9cb76d9007..28799c1192 100644
--- a/tez-api/src/main/java/org/apache/tez/common/TezCommonUtils.java
+++ b/tez-api/src/main/java/org/apache/tez/common/TezCommonUtils.java
@@ -22,10 +22,10 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
+import java.util.stream.Collectors;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
@@ -38,6 +38,7 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
@@ -55,7 +56,7 @@
import com.google.protobuf.ByteString;
@Private
-public class TezCommonUtils {
+public final class TezCommonUtils {
public static final FsPermission TEZ_AM_DIR_PERMISSION = FsPermission
.createImmutable((short) 0700); // rwx--------
public static final FsPermission TEZ_AM_FILE_PERMISSION = FsPermission
@@ -64,6 +65,8 @@ public class TezCommonUtils {
public static final String TEZ_SYSTEM_SUB_DIR = ".tez";
+ private TezCommonUtils() {}
+
/**
*
* This function returns the staging directory defined in the config with
@@ -73,7 +76,7 @@ public class TezCommonUtils {
* function makes sure if the staging directory exists. If not, it creates the
* directory with permission TEZ_AM_DIR_PERMISSION.
*
- *
+ *
* @param conf
* TEZ configuration
* @return Fully qualified staging directory
@@ -103,7 +106,7 @@ public static Path getTezBaseStagingPath(Configuration conf) {
* sub-directory (TEZ_SYSTEM_SUB_DIR/) under the base
* staging directory, often provided by user.
*
- *
+ *
* @param conf
* Tez configuration
* @param strAppId
@@ -134,7 +137,7 @@ public static Path createTezSystemStagingPath(Configuration conf, String strAppI
* its temporary files under this sub-directory. The function normally doesn't
* creates any sub-directory under the base staging directory.
*
- *
+ *
* @param tezSysStagingPath
* TEZ system level staging directory used for Tez internals
* @return path to configuration
@@ -168,7 +171,7 @@ public static Path getTezConfStagingPath(Path tezSysStagingPath) {
*
* Returns a path to store local resources/session jars
*
- *
+ *
* @param tezSysStagingPath
* TEZ system level staging directory used for Tez internals
* @return path to store the session jars
@@ -182,7 +185,7 @@ public static Path getTezAMJarStagingPath(Path tezSysStagingPath) {
*
* Returns a path to store binary plan
*
- *
+ *
* @param tezSysStagingPath
* TEZ system level staging directory used for Tez internals
* @return path to store the plan in binary
@@ -196,7 +199,7 @@ public static Path getTezBinPlanStagingPath(Path tezSysStagingPath) {
*
* Returns a path to store text plan
*
- *
+ *
* @param tezSysStagingPath
* TEZ system level staging directory used for Tez internals
* @param strAppId
@@ -216,28 +219,27 @@ public static Path getTezTextPlanStagingPath(Path tezSysStagingPath, String strA
*
* Returns a path to store recovery information
*
- *
+ *
* @param tezSysStagingPath
* TEZ system level staging directory used for Tez internals
* @param conf
* Tez configuration
* @return App recovery path
- * @throws IOException
*/
@Private
public static Path getRecoveryPath(Path tezSysStagingPath, Configuration conf)
throws IOException {
- Path baseReecoveryPath = new Path(tezSysStagingPath,
+ Path baseRecoveryPath = new Path(tezSysStagingPath,
TezConstants.DAG_RECOVERY_DATA_DIR_NAME);
- FileSystem recoveryFS = baseReecoveryPath.getFileSystem(conf);
- return recoveryFS.makeQualified(baseReecoveryPath);
+ FileSystem recoveryFS = baseRecoveryPath.getFileSystem(conf);
+ return recoveryFS.makeQualified(baseRecoveryPath);
}
/**
*
* Returns a path to store app attempt specific recovery details
*
- *
+ *
* @param recoveryPath
* TEZ recovery directory used for Tez internals
* @param attemptID
@@ -253,7 +255,7 @@ public static Path getAttemptRecoveryPath(Path recoveryPath, int attemptID) {
*
* Returns a path to store DAG specific recovery info
*
- *
+ *
* @param attemptRecoverPath
* :TEZ system level staging directory used for Tez internals
* @param dagID
@@ -269,7 +271,7 @@ public static Path getDAGRecoveryPath(Path attemptRecoverPath, String dagID) {
*
* Returns a path to store summary info for recovery
*
- *
+ *
* @param attemptRecoverPath
* TEZ system level staging directory used for Tez internals
* @return Summary event path used in recovery
@@ -283,15 +285,22 @@ public static Path getSummaryRecoveryPath(Path attemptRecoverPath) {
*
* Create a directory with predefined directory permission
*
- *
+ *
* @param fs
* Filesystem
* @param dir
* directory to be created
- * @throws IOException
*/
public static void mkDirForAM(FileSystem fs, Path dir) throws IOException {
- fs.mkdirs(dir, new FsPermission(TEZ_AM_DIR_PERMISSION));
+ FsPermission perm = new FsPermission(TEZ_AM_DIR_PERMISSION);
+ fs.mkdirs(dir, perm);
+ FileStatus fileStatus = fs.getFileStatus(dir);
+ if (!fileStatus.getPermission().equals(perm)) {
+ LOG.warn("Directory " + dir.toString() + " created with unexpected permissions : "
+ + fileStatus.getPermission() + ". Fixing permissions to correct value : "
+ + perm.toString());
+ fs.setPermission(dir, perm);
+ }
}
/**
@@ -299,18 +308,17 @@ public static void mkDirForAM(FileSystem fs, Path dir) throws IOException {
* Create a file with TEZ_AM_FILE_PERMISSION permission and
* returns OutputStream
*
- *
+ *
* @param fs
* Filesystem
* @param filePath
* file path to create the file
* @return FSDataOutputStream
- * @throws IOException
*/
public static FSDataOutputStream createFileForAM(FileSystem fs, Path filePath) throws IOException {
return FileSystem.create(fs, filePath, new FsPermission(TEZ_AM_FILE_PERMISSION));
}
-
+
public static void addAdditionalLocalResources(Map additionalLrs,
Map originalLRs, String logContext) {
// TODO TEZ-1798. Handle contents of Tez archives for duplicate LocalResource checks
@@ -388,31 +396,38 @@ public static ByteString compressByteArrayToByteString(byte[] inBytes, Deflater
@Private
public static byte[] decompressByteStringToByteArray(ByteString byteString) throws IOException {
- return decompressByteStringToByteArray(byteString, newInflater());
+ Inflater inflater = newInflater();
+ try {
+ return decompressByteStringToByteArray(byteString, inflater);
+ } finally {
+ inflater.end();
+ }
}
@Private
public static byte[] decompressByteStringToByteArray(ByteString byteString, Inflater inflater) throws IOException {
inflater.reset();
- return IOUtils.toByteArray(new InflaterInputStream(byteString.newInput(), inflater));
-
+ try (InflaterInputStream inflaterInputStream = new InflaterInputStream(byteString.newInput(), inflater)) {
+ return IOUtils.toByteArray(inflaterInputStream);
+ }
}
public static String getCredentialsInfo(Credentials credentials, String identifier) {
+ if (credentials == null) {
+ return "Credentials: #" + identifier + "Tokens=null";
+ }
+
StringBuilder sb = new StringBuilder();
- sb.append("Credentials: #" + identifier + "Tokens=").append(credentials.numberOfTokens());
+ sb.append("Credentials: #").append(identifier).append("Tokens=").append(credentials.numberOfTokens());
if (credentials.numberOfTokens() > 0) {
sb.append(", Services=");
- Iterator> tokenItr = credentials.getAllTokens().iterator();
- if (tokenItr.hasNext()) {
- Token token = tokenItr.next();
- sb.append(token.getService()).append("(").append(token.getKind()).append(")");
+ sb.append(credentials.getAllTokens().stream()
+ .map(t -> String.format("%s(%s)", t.getService(), t.getKind()))
+ .collect(Collectors.joining(",")));
- }
- while(tokenItr.hasNext()) {
- Token token = tokenItr.next();
- sb.append(",").append(token.getService()).append("(").append(token.getKind()).append(")");
- }
+ sb.append(", TokenDetails=");
+ sb.append(credentials.getAllTokens().stream().map(Token::toString)
+ .collect(Collectors.joining(",")));
}
return sb.toString();
}
@@ -421,16 +436,14 @@ public static ByteBuffer convertJobTokenToBytes(
Token jobToken) throws IOException {
DataOutputBuffer dob = new DataOutputBuffer();
jobToken.write(dob);
- ByteBuffer bb = ByteBuffer.wrap(dob.getData(), 0, dob.getLength());
- return bb;
+ return ByteBuffer.wrap(dob.getData(), 0, dob.getLength());
}
public static Credentials parseCredentialsBytes(byte[] credentialsBytes) throws IOException {
Credentials credentials = new Credentials();
DataInputBuffer dib = new DataInputBuffer();
try {
- byte[] tokenBytes = credentialsBytes;
- dib.reset(tokenBytes, tokenBytes.length);
+ dib.reset(credentialsBytes, credentialsBytes.length);
credentials.readTokenStorageStream(dib);
return credentials;
} finally {
@@ -445,7 +458,7 @@ public static void logCredentials(Logger log, Credentials credentials, String id
}
public static Collection tokenizeString(String str, String delim) {
- List values = new ArrayList();
+ List values = new ArrayList<>();
if (str == null || str.isEmpty())
return values;
StringTokenizer tokenizer = new StringTokenizer(str, delim);
@@ -519,7 +532,7 @@ public static long getAMClientHeartBeatTimeoutMillis(Configuration conf) {
if (val > 0 && val < TezConstants.TEZ_AM_CLIENT_HEARTBEAT_TIMEOUT_SECS_MINIMUM) {
return TezConstants.TEZ_AM_CLIENT_HEARTBEAT_TIMEOUT_SECS_MINIMUM * 1000;
}
- return val * 1000;
+ return val * 1000L;
}
/**
@@ -556,7 +569,13 @@ public static long getDAGSessionTimeout(Configuration conf) {
if (timeoutSecs == 0) {
timeoutSecs = 1;
}
- return 1000l * timeoutSecs;
+ return 1000L * timeoutSecs;
}
+ public static int getJavaVersion() {
+ String javaVersionString = System.getProperty("java.version");
+ return javaVersionString.split("\\.")[0].equals("1")
+ ? Integer.parseInt(javaVersionString.split("\\.")[1]) // "1.8" -> 8
+ : Integer.parseInt(javaVersionString.split("\\.")[0]); // "9.x" -> 9, "11.x" -> 11
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/TezUtils.java b/tez-api/src/main/java/org/apache/tez/common/TezUtils.java
index dfdf9fa642..88920a4e53 100644
--- a/tez-api/src/main/java/org/apache/tez/common/TezUtils.java
+++ b/tez-api/src/main/java/org/apache/tez/common/TezUtils.java
@@ -20,17 +20,16 @@
import java.io.IOException;
import java.io.OutputStream;
-import java.util.Iterator;
+import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.InflaterInputStream;
+import java.util.Objects;
-import com.google.common.base.Preconditions;
import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedInputStream;
+import org.apache.tez.runtime.api.TaskContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.classification.InterfaceAudience;
@@ -41,16 +40,20 @@
import org.apache.tez.dag.api.records.DAGProtos;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
+import org.xerial.snappy.SnappyInputStream;
+import org.xerial.snappy.SnappyOutputStream;
/**
* Utility methods for setting up a DAG. Has helpers for setting up log4j configuration, converting
* {@link org.apache.hadoop.conf.Configuration} to {@link org.apache.tez.dag.api.UserPayload} etc.
*/
@InterfaceAudience.Public
-public class TezUtils {
+public final class TezUtils {
private static final Logger LOG = LoggerFactory.getLogger(TezUtils.class);
+ private TezUtils() {}
+
/**
* Allows changing the log level for task / AM logging.
*
@@ -71,19 +74,12 @@ public static void addLog4jSystemProperties(String logLevel,
* @param conf
* : Configuration to be converted
* @return PB ByteString (compressed)
- * @throws java.io.IOException
*/
public static ByteString createByteStringFromConf(Configuration conf) throws IOException {
- Preconditions.checkNotNull(conf, "Configuration must be specified");
+ Objects.requireNonNull(conf, "Configuration must be specified");
ByteString.Output os = ByteString.newOutput();
- DeflaterOutputStream compressOs = new DeflaterOutputStream(os,
- new Deflater(Deflater.BEST_SPEED));
- try {
+ try (SnappyOutputStream compressOs = new SnappyOutputStream(os)) {
writeConfInPB(compressOs, conf);
- } finally {
- if (compressOs != null) {
- compressOs.close();
- }
}
return os.toByteString();
}
@@ -94,10 +90,15 @@ public static ByteString createByteStringFromConf(Configuration conf) throws IOE
*
* @param conf configuration to be converted
* @return an instance of {@link org.apache.tez.dag.api.UserPayload}
- * @throws java.io.IOException
*/
public static UserPayload createUserPayloadFromConf(Configuration conf) throws IOException {
- return UserPayload.create(createByteStringFromConf(conf).asReadOnlyByteBuffer());
+ return UserPayload.create(ByteBuffer.wrap(createByteStringFromConf(conf).toByteArray()));
+ }
+
+ private static DAGProtos.ConfigurationProto createConfProto(SnappyInputStream uncompressIs) throws IOException {
+ CodedInputStream in = CodedInputStream.newInstance(uncompressIs);
+ in.setSizeLimit(Integer.MAX_VALUE);
+ return DAGProtos.ConfigurationProto.parseFrom(in);
}
/**
@@ -106,17 +107,39 @@ public static UserPayload createUserPayloadFromConf(Configuration conf) throws I
* @param byteString byteString representation of the conf created using {@link
* #createByteStringFromConf(org.apache.hadoop.conf.Configuration)}
* @return Configuration
- * @throws java.io.IOException
*/
public static Configuration createConfFromByteString(ByteString byteString) throws IOException {
- Preconditions.checkNotNull(byteString, "ByteString must be specified");
- // SnappyInputStream uncompressIs = new
- // SnappyInputStream(byteString.newInput());
- InflaterInputStream uncompressIs = new InflaterInputStream(byteString.newInput());
- DAGProtos.ConfigurationProto confProto = DAGProtos.ConfigurationProto.parseFrom(uncompressIs);
- Configuration conf = new Configuration(false);
- readConfFromPB(confProto, conf);
- return conf;
+ Objects.requireNonNull(byteString, "ByteString must be specified");
+ try(SnappyInputStream uncompressIs = new SnappyInputStream(byteString.newInput())) {
+ DAGProtos.ConfigurationProto confProto = createConfProto(uncompressIs);
+ Configuration conf = new Configuration(false);
+ readConfFromPB(confProto, conf);
+ TezClassLoader.setupForConfiguration(conf);
+ return conf;
+ }
+ }
+
+ public static Configuration createConfFromBaseConfAndPayload(TaskContext context)
+ throws IOException {
+ Configuration baseConf = context.getContainerConfiguration();
+ Configuration configuration = new Configuration(baseConf);
+ UserPayload payload = context.getUserPayload();
+ ByteString byteString = ByteString.copyFrom(payload.getPayload());
+ try(SnappyInputStream uncompressIs = new SnappyInputStream(byteString.newInput())) {
+ DAGProtos.ConfigurationProto confProto = createConfProto(uncompressIs);
+ readConfFromPB(confProto, configuration);
+ TezClassLoader.setupForConfiguration(configuration);
+ return configuration;
+ }
+ }
+
+ public static void addToConfFromByteString(Configuration configuration, ByteString byteString)
+ throws IOException {
+ try(SnappyInputStream uncompressIs = new SnappyInputStream(byteString.newInput())) {
+ DAGProtos.ConfigurationProto confProto = createConfProto(uncompressIs);
+ readConfFromPB(confProto, configuration);
+ TezClassLoader.setupForConfiguration(configuration);
+ }
}
/**
@@ -126,7 +149,6 @@ public static Configuration createConfFromByteString(ByteString byteString) thro
* @param payload {@link org.apache.tez.dag.api.UserPayload} created using {@link
* #createUserPayloadFromConf(org.apache.hadoop.conf.Configuration)}
* @return Configuration
- * @throws java.io.IOException
*/
public static Configuration createConfFromUserPayload(UserPayload payload) throws IOException {
return createConfFromByteString(ByteString.copyFrom(payload.getPayload()));
@@ -134,16 +156,8 @@ public static Configuration createConfFromUserPayload(UserPayload payload) throw
private static void writeConfInPB(OutputStream dos, Configuration conf) throws IOException {
- DAGProtos.ConfigurationProto.Builder confProtoBuilder = DAGProtos.ConfigurationProto
- .newBuilder();
- Iterator> iter = conf.iterator();
- while (iter.hasNext()) {
- Map.Entry entry = iter.next();
- DAGProtos.PlanKeyValuePair.Builder kvp = DAGProtos.PlanKeyValuePair.newBuilder();
- kvp.setKey(entry.getKey());
- kvp.setValue(entry.getValue());
- confProtoBuilder.addConfKeyValues(kvp);
- }
+ DAGProtos.ConfigurationProto.Builder confProtoBuilder = DAGProtos.ConfigurationProto.newBuilder();
+ populateConfProtoFromEntries(conf, confProtoBuilder);
DAGProtos.ConfigurationProto confProto = confProtoBuilder.build();
confProto.writeTo(dos);
}
@@ -164,10 +178,14 @@ public static String convertToHistoryText(String description, Configuration conf
}
if (conf != null) {
JSONObject confJson = new JSONObject();
- Iterator> iter = conf.iterator();
- while (iter.hasNext()) {
- Entry entry = iter.next();
- confJson.put(entry.getKey(), conf.get(entry.getKey()));
+ for (Entry entry : conf) {
+ String key = entry.getKey();
+ String val = conf.get(entry.getKey());
+ if (val != null) {
+ confJson.put(key, val);
+ } else {
+ LOG.debug("null value in Configuration after replacement for key={}. Skipping.", key);
+ }
}
jsonObject.put(ATSConstants.CONFIG, confJson);
}
@@ -181,4 +199,22 @@ public static String convertToHistoryText(Configuration conf) {
return convertToHistoryText(null, conf);
}
+
+ /* Copy each Map.Entry with non-null value to DAGProtos.ConfigurationProto */
+ public static void populateConfProtoFromEntries(Iterable> params,
+ DAGProtos.ConfigurationProto.Builder confBuilder) {
+ for(Map.Entry entry : params) {
+ String key = entry.getKey();
+ String val = entry.getValue();
+ if(val != null) {
+ DAGProtos.PlanKeyValuePair.Builder kvp = DAGProtos.PlanKeyValuePair.newBuilder();
+ kvp.setKey(key);
+ kvp.setValue(val);
+ confBuilder.addConfKeyValues(kvp);
+ } else {
+ LOG.debug("null value for key={}. Skipping.", key);
+ }
+ }
+ }
+
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/TezYARNUtils.java b/tez-api/src/main/java/org/apache/tez/common/TezYARNUtils.java
index bd6de11a59..1e5d4bdf4a 100644
--- a/tez-api/src/main/java/org/apache/tez/common/TezYARNUtils.java
+++ b/tez-api/src/main/java/org/apache/tez/common/TezYARNUtils.java
@@ -35,7 +35,7 @@
import org.apache.tez.dag.api.TezConstants;
@Private
-public class TezYARNUtils {
+public final class TezYARNUtils {
private static Logger LOG = LoggerFactory.getLogger(TezYARNUtils.class);
public static final String ENV_NAME_REGEX = "[A-Za-z_][A-Za-z0-9_]*";
@@ -49,6 +49,8 @@ public class TezYARNUtils {
+ "([^,]*)" // val group
);
+ private TezYARNUtils() {}
+
public static String getFrameworkClasspath(Configuration conf, boolean usingArchive) {
StringBuilder classpathBuilder = new StringBuilder();
boolean userClassesTakesPrecedence =
@@ -126,9 +128,11 @@ private static void addUserSpecifiedClasspath(StringBuilder classpathBuilder,
// Add PWD:PWD/*
classpathBuilder.append(Environment.PWD.$())
- .append(File.pathSeparator)
- .append(Environment.PWD.$() + File.separator + "*")
- .append(File.pathSeparator);
+ .append(File.pathSeparator)
+ .append(Environment.PWD.$())
+ .append(File.separator)
+ .append("*")
+ .append(File.pathSeparator);
}
public static void appendToEnvFromInputString(Map env,
@@ -161,7 +165,7 @@ public static void appendToEnvFromInputString(Map env,
public static void setEnvIfAbsentFromInputString(Map env,
String envString) {
if (envString != null && envString.length() > 0) {
- String childEnvs[] = envString.split(",");
+ String[] childEnvs = envString.split(",");
for (String cEnv : childEnvs) {
String[] parts = cEnv.split("="); // split on '='
Matcher m = VAR_SUBBER .matcher(parts[1]);
diff --git a/tez-api/src/main/java/org/apache/tez/common/VersionInfo.java b/tez-api/src/main/java/org/apache/tez/common/VersionInfo.java
index 9f98974314..1afde0d3f4 100644
--- a/tez-api/src/main/java/org/apache/tez/common/VersionInfo.java
+++ b/tez-api/src/main/java/org/apache/tez/common/VersionInfo.java
@@ -42,6 +42,8 @@ public class VersionInfo {
private static final String VERSION = "version";
private static final String REVISION = "revision";
private static final String BUILD_TIME = "buildtime";
+ private static final String BUILD_USER = "builduser";
+ private static final String BUILD_JAVA_VERSION = "buildjavaversion";
private static final String SCM_URL = "scmurl";
public static final String UNKNOWN = "Unknown";
@@ -66,13 +68,15 @@ protected VersionInfo(String component) {
@VisibleForTesting
@Private
- protected VersionInfo(String component, String version, String revision,
- String buildTime, String scmUrl) {
+ protected VersionInfo(String component, String version, String revision, String buildTime,
+ String scmUrl) {
this.info = new Properties();
this.component = component;
info.setProperty(VERSION, version);
info.setProperty(REVISION, revision);
info.setProperty(BUILD_TIME, buildTime);
+ info.setProperty(BUILD_USER, System.getProperty("user.name"));
+ info.setProperty(BUILD_JAVA_VERSION, System.getProperty("java.version"));
info.setProperty(SCM_URL, scmUrl);
}
@@ -84,6 +88,14 @@ public String getBuildTime() {
return info.getProperty(BUILD_TIME, UNKNOWN);
}
+ public String getBuildUser() {
+ return info.getProperty(BUILD_USER, UNKNOWN);
+ }
+
+ public String getBuildJavaVersion() {
+ return info.getProperty(BUILD_JAVA_VERSION, UNKNOWN);
+ }
+
public String getRevision() {
return info.getProperty(REVISION, UNKNOWN);
}
@@ -99,6 +111,8 @@ public String toString() {
+ ", revision=" + getRevision()
+ ", SCM-URL=" + getSCMURL()
+ ", buildTime=" + getBuildTime()
+ + ", buildUser=" + getBuildUser()
+ + ", buildJavaVersion=" + getBuildJavaVersion()
+ " ]";
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounter.java
index 7bc1109518..befc7c023e 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounter.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounter.java
@@ -49,4 +49,9 @@ public synchronized boolean equals(Object genericRight) {
public synchronized int hashCode() {
return Objects.hashCode(getName(), getDisplayName(), getValue());
}
+
+ @Override
+ public String toString() {
+ return "[" + getClass().getSimpleName() + "]: " + getDisplayName() + "=" + getValue();
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounterGroup.java b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounterGroup.java
index a4b153f6cd..1d1b56d062 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounterGroup.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounterGroup.java
@@ -194,10 +194,15 @@ public synchronized int hashCode() {
@Override
public void incrAllCounters(CounterGroupBase rightGroup) {
+ aggrAllCounters(rightGroup);
+ }
+
+ @Override
+ public void aggrAllCounters(CounterGroupBase rightGroup) {
try {
for (TezCounter right : rightGroup) {
TezCounter left = findCounter(right.getName(), right.getDisplayName());
- left.increment(right.getValue());
+ left.aggregate(right);
}
} catch (LimitExceededException e) {
counters.clear();
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounters.java b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounters.java
index 470cb78fdd..58f73b68bd 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounters.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AbstractCounters.java
@@ -354,13 +354,22 @@ public synchronized String toString() {
* @param other the other Counters instance
*/
public synchronized void incrAllCounters(AbstractCounters other) {
+ aggrAllCounters(other);
+ }
+
+ /**
+ * Increments multiple counters by their amounts in another Counters
+ * instance.
+ * @param other the other Counters instance
+ */
+ public synchronized void aggrAllCounters(AbstractCounters other) {
for(G right : other) {
String groupName = right.getName();
G left = (isFrameworkGroup(groupName) ? fgroups : groups).get(groupName);
if (left == null) {
left = addGroup(groupName, right.getDisplayName());
}
- left.incrAllCounters(right);
+ left.aggrAllCounters(right);
}
}
@@ -392,7 +401,7 @@ public void setWriteAllCounters(boolean send) {
/**
* Get the "writeAllCounters" option
- * @return true of all counters would serialized
+ * @return true if all counters would be serialized
*/
@InterfaceAudience.Private
public boolean getWriteAllCounters() {
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AggregateFrameworkCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateFrameworkCounter.java
new file mode 100644
index 0000000000..aa7d4462cf
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateFrameworkCounter.java
@@ -0,0 +1,85 @@
+/**
+ * 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.tez.common.counters;
+
+import org.apache.tez.common.counters.FrameworkCounterGroup.FrameworkCounter;
+
+@SuppressWarnings("rawtypes")
+public class AggregateFrameworkCounter> extends FrameworkCounter implements AggregateTezCounter {
+
+ private long min = Long.MAX_VALUE;
+ private long max = Long.MIN_VALUE;
+ private long count = 0;
+
+ @SuppressWarnings("unchecked")
+ public AggregateFrameworkCounter(Enum ref, String groupName) {
+ super(ref, groupName);
+ }
+
+ @Override
+ public void increment(long incr) {
+ throw new IllegalArgumentException("Cannot increment an aggregate counter directly");
+ }
+
+ @Override
+ public void aggregate(TezCounter other) {
+ final long val = other.getValue();
+ final long othermax;
+ final long othermin;
+ final long othercount;
+ if (other instanceof AggregateTezCounter) {
+ othermax = ((AggregateTezCounter) other).getMax();
+ othermin = ((AggregateTezCounter) other).getMin();
+ othercount = ((AggregateTezCounter) other).getCount();
+ } else {
+ othermin = othermax = val;
+ othercount = 1;
+ }
+ this.count += othercount;
+ super.increment(val);
+ if (this.min == Long.MAX_VALUE) {
+ this.min = othermin;
+ this.max = othermax;
+ return;
+ }
+ this.min = Math.min(this.min, othermin);
+ this.max = Math.max(this.max, othermax);
+ }
+
+ @Override
+ public long getMin() {
+ return min;
+ }
+
+ @Override
+ public long getMax() {
+ return max;
+ }
+
+ @SuppressWarnings("unchecked")
+ public FrameworkCounter asFrameworkCounter() {
+ return ((FrameworkCounter)this);
+ }
+
+ @Override
+ public long getCount() {
+ return count;
+ }
+
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounter.java
new file mode 100644
index 0000000000..bf711dae86
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounter.java
@@ -0,0 +1,31 @@
+/**
+ * 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.tez.common.counters;
+
+public interface AggregateTezCounter {
+
+ public abstract void aggregate(TezCounter other);
+
+ public abstract long getMin();
+
+ public abstract long getMax();
+
+ public abstract long getCount();
+
+}
\ No newline at end of file
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounterDelegate.java b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounterDelegate.java
new file mode 100644
index 0000000000..ae2ca7b0c6
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounterDelegate.java
@@ -0,0 +1,118 @@
+/**
+ * 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.tez.common.counters;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class AggregateTezCounterDelegate extends AbstractCounter implements AggregateTezCounter {
+
+ private final T child;
+ private long min = Long.MAX_VALUE;
+ private long max = Long.MIN_VALUE;
+ private long count = 0;
+
+ public AggregateTezCounterDelegate(T child) {
+ this.child = child;
+ }
+
+ @Override
+ public String getName() {
+ return child.getName(); // this is a pass-through
+ }
+
+ @Override
+ public String getDisplayName() {
+ return child.getDisplayName();
+ }
+
+ @Override
+ public long getValue() {
+ return child.getValue();
+ }
+
+ @Override
+ public void setValue(long value) {
+ this.child.setValue(value);
+ }
+
+ @Override
+ public void increment(long incr) {
+ throw new UnsupportedOperationException("Cannot increment an aggregate counter");
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.tez.common.counters.AggregateTezCounter#aggregate(org.apache.tez.common.counters.TezCounter)
+ */
+ @Override
+ public void aggregate(TezCounter other) {
+ final long val = other.getValue();
+ final long othermax;
+ final long othermin;
+ final long othercount;
+ if (other instanceof AggregateTezCounter) {
+ othermax = ((AggregateTezCounter) other).getMax();
+ othermin = ((AggregateTezCounter) other).getMin();
+ othercount = ((AggregateTezCounter) other).getCount();
+ } else {
+ othermin = othermax = val;
+ othercount = 1;
+ }
+ this.count += othercount;
+ this.child.increment(val);
+ if (this.min == Long.MAX_VALUE) {
+ this.min = othermin;
+ this.max = othermax;
+ return;
+ }
+ this.min = Math.min(this.min, othermin);
+ this.max = Math.max(this.max, othermax);
+ }
+
+ @Override
+ public TezCounter getUnderlyingCounter() {
+ return this.child;
+ }
+
+ @Override
+ public void readFields(DataInput arg0) throws IOException {
+ throw new UnsupportedOperationException("Cannot deserialize an aggregate counter");
+ }
+
+ @Override
+ public void write(DataOutput arg0) throws IOException {
+ throw new UnsupportedOperationException("Cannot deserialize an aggregate counter");
+ }
+
+ @Override
+ public long getMin() {
+ return min;
+ }
+
+ @Override
+ public long getMax() {
+ return max;
+ }
+
+ @Override
+ public long getCount() {
+ return count;
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounters.java b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounters.java
new file mode 100644
index 0000000000..332c24a960
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/AggregateTezCounters.java
@@ -0,0 +1,119 @@
+/**
+ * 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.tez.common.counters;
+
+public class AggregateTezCounters extends TezCounters {
+
+ private static final GroupFactory groupFactory = new GroupFactory();
+
+ public AggregateTezCounters() {
+ super(groupFactory);
+ }
+
+ // Mix framework group implementation into CounterGroup interface
+ private static class AggregateFrameworkGroupImpl>
+ extends FrameworkCounterGroup implements CounterGroup {
+
+ AggregateFrameworkGroupImpl(Class cls) {
+ super(cls);
+ }
+
+ @Override
+ protected FrameworkCounter newCounter(T key) {
+ return (new AggregateFrameworkCounter(key, getName()))
+ .asFrameworkCounter();
+ }
+
+ @Override
+ public CounterGroupBase getUnderlyingGroup() {
+ return this;
+ }
+ }
+
+ // Mix generic group implementation into CounterGroup interface
+ // and provide some mandatory group factory methods.
+ private static class AggregateGenericGroup extends AbstractCounterGroup
+ implements CounterGroup {
+
+ AggregateGenericGroup(String name, String displayName, Limits limits) {
+ super(name, displayName, limits);
+ }
+
+ @Override
+ protected TezCounter newCounter(String name, String displayName, long value) {
+ return new AggregateTezCounterDelegate(new GenericCounter(name, displayName, value));
+ }
+
+ @Override
+ protected TezCounter newCounter() {
+ return new AggregateTezCounterDelegate(new GenericCounter());
+ }
+
+ @Override
+ public CounterGroupBase getUnderlyingGroup() {
+ return this;
+ }
+ }
+
+ // Mix file system group implementation into the CounterGroup interface
+ private static class AggregateFileSystemGroup extends FileSystemCounterGroup
+ implements CounterGroup {
+
+ @Override
+ protected TezCounter newCounter(String scheme, FileSystemCounter key) {
+ return new AggregateTezCounterDelegate(new FSCounter(scheme, key));
+ }
+
+ @Override
+ public CounterGroupBase getUnderlyingGroup() {
+ return this;
+ }
+ }
+
+ /**
+ * Provide factory methods for counter group factory implementation.
+ * See also the GroupFactory in
+ * {@link org.apache.hadoop.TezCounters.Counters mapred.Counters}
+ */
+ private static class GroupFactory
+ extends CounterGroupFactory {
+
+ @Override
+ protected >
+ FrameworkGroupFactory
+ newFrameworkGroupFactory(final Class cls) {
+ return new FrameworkGroupFactory() {
+ @Override public CounterGroup newGroup(String name) {
+ return new AggregateFrameworkGroupImpl(cls); // impl in this package
+ }
+ };
+ }
+
+ @Override
+ protected CounterGroup newGenericGroup(String name, String displayName,
+ Limits limits) {
+ return new AggregateGenericGroup(name, displayName, limits);
+ }
+
+ @Override
+ protected CounterGroup newFileSystemGroup() {
+ return new AggregateFileSystemGroup();
+ }
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/CounterGroupBase.java b/tez-api/src/main/java/org/apache/tez/common/counters/CounterGroupBase.java
index be4bf77e83..ebcc7b0e21 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/CounterGroupBase.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/CounterGroupBase.java
@@ -76,7 +76,7 @@ public interface CounterGroupBase
/**
* Find a counter in the group
* @param counterName the name of the counter
- * @param create create the counter if not found if true
+ * @param create create the counter if not found is true
* @return the counter that was found or added or null if create is false
*/
T findCounter(String counterName, boolean create);
@@ -97,8 +97,17 @@ public interface CounterGroupBase
* Increment all counters by a group of counters
* @param rightGroup the group to be added to this group
*/
+ @Deprecated
void incrAllCounters(CounterGroupBase rightGroup);
-
+
+ /**
+ * Aggregate all counters by a group of counters
+ * @param rightGroup the group to be added to this group
+ */
+ public default void aggrAllCounters(CounterGroupBase rightGroup) {
+ incrAllCounters(rightGroup);
+ }
+
@Private
/**
* Exposes the underlying group type if a facade.
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/DAGCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/DAGCounter.java
index 5064c35c5a..ca575d4dfa 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/DAGCounter.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/DAGCounter.java
@@ -22,6 +22,7 @@
import org.apache.hadoop.classification.InterfaceStability;
// Per-job counters
+// Keep in sync with tez-ui/src/main/webapp/config/default-app-conf.js
@InterfaceAudience.Public
@InterfaceStability.Evolving
public enum DAGCounter {
@@ -29,6 +30,28 @@ public enum DAGCounter {
NUM_KILLED_TASKS,
NUM_SUCCEEDED_TASKS,
TOTAL_LAUNCHED_TASKS,
+
+ /* The durations of task attempts are categorized based on their final states. The duration of successful tasks
+ can serve as a reference when analyzing the durations of failed or killed tasks. This is because solely examining
+ failed or killed task durations may be misleading, as these durations are measured from the submission time,
+ which does not always correspond to the actual start time of the task attempt on executor nodes
+ (e.g., in scenarios involving Hive LLAP).
+ These counters align with the duration metrics used for WALL_CLOCK_MILLIS.
+ As such, the following relationship applies:
+ WALL_CLOCK_MILLIS = DURATION_FAILED_TASKS_MILLIS + DURATION_KILLED_TASKS_MILLIS + DURATION_SUCCEEDED_TASKS_MILLIS
+ */
+
+ // Total amount of time spent on running FAILED task attempts. This can be blamed for performance degradation, as a
+ // DAG can still finish successfully in the presence of failed attempts.
+ DURATION_FAILED_TASKS_MILLIS,
+
+ // Total amount of time spent on running KILLED task attempts.
+ DURATION_KILLED_TASKS_MILLIS,
+
+ // Total amount of time spent on running SUCCEEDED task attempts, which can be a reference together with the same for
+ // FAILED and KILLED attempts.
+ DURATION_SUCCEEDED_TASKS_MILLIS,
+
OTHER_LOCAL_TASKS,
DATA_LOCAL_TASKS,
RACK_LOCAL_TASKS,
@@ -38,5 +61,66 @@ public enum DAGCounter {
NUM_UBER_SUBTASKS,
NUM_FAILED_UBERTASKS,
AM_CPU_MILLISECONDS,
- AM_GC_TIME_MILLIS
+ /** Wall clock time taken by all the tasks. */
+ WALL_CLOCK_MILLIS,
+ AM_GC_TIME_MILLIS,
+
+ /*
+ * Type: # of containers
+ * Both allocated and launched containers before DAG start.
+ * This is incremented only once when the DAG starts and it's calculated
+ * by querying all the held containers from TaskSchedulers.
+ */
+ INITIAL_HELD_CONTAINERS,
+
+ /*
+ * Type: # of containers
+ * All containers that have been seen/used in this DAG by task allocation.
+ * This counter can be calculated at the end of DAG by simply counting the distinct
+ * ContainerIds that have been seen in TaskSchedulerManager.taskAllocated callbacks.
+ */
+ TOTAL_CONTAINERS_USED,
+
+ /*
+ * Type: # of events
+ * Number of container allocations during a DAG. This is incremented every time
+ * the containerAllocated callback is called in the TaskSchedulerContext.
+ * This counter doesn't account for initially held (launched, allocated) containers.
+ */
+ TOTAL_CONTAINER_ALLOCATION_COUNT,
+
+ /*
+ * Type: # of events
+ * Number of container launches during a DAG. This is incremented every time
+ * the containerLaunched callback is called in the ContainerLauncherContext.
+ * This counter doesn't account for initially held (launched, allocated) containers.
+ */
+ TOTAL_CONTAINER_LAUNCH_COUNT,
+
+ /*
+ * Type: # of events
+ * Number of container releases during a DAG. This is incremented every time
+ * the containerBeingReleased callback is called in the TaskSchedulerContext.
+ */
+ TOTAL_CONTAINER_RELEASE_COUNT,
+
+ /*
+ * Type: # of events
+ * Number of container reuses during a DAG. This is incremented every time
+ * the containerReused callback is called in the TaskSchedulerContext.
+ */
+ TOTAL_CONTAINER_REUSE_COUNT,
+
+ /*
+ * Number of nodes to which task attempts were assigned in this DAG.
+ * Nodes are distinguished by the Yarn NodeId.getHost().
+ */
+ NODE_USED_COUNT,
+
+ /*
+ * Total number of nodes visible to the task scheduler (regardless of
+ * task assignments). This is typically exposed by a resource manager
+ * client.
+ */
+ NODE_TOTAL_COUNT
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounter.java
index 73e358179b..fdb93f1194 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounter.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounter.java
@@ -19,16 +19,68 @@
package org.apache.tez.common.counters;
import org.apache.hadoop.classification.InterfaceAudience.Private;
+import org.apache.hadoop.fs.StorageStatistics.CommonStatisticNames;
+/**
+ * FileSystemCounter is an enum for defining which filesystem/storage statistics are exposed in Tez.
+ */
@Private
public enum FileSystemCounter {
- BYTES_READ,
- BYTES_WRITTEN,
- READ_OPS,
- LARGE_READ_OPS,
- WRITE_OPS,
- HDFS_BYTES_READ,
- HDFS_BYTES_WRITTEN,
- FILE_BYTES_READ,
- FILE_BYTES_WRITTEN
+ BYTES_READ("bytesRead"),
+ BYTES_WRITTEN("bytesWritten"),
+ READ_OPS("readOps"),
+ LARGE_READ_OPS("largeReadOps"),
+ WRITE_OPS("writeOps"),
+
+ // Additional counters from HADOOP-13305
+ OP_APPEND(CommonStatisticNames.OP_APPEND),
+ OP_COPY_FROM_LOCAL_FILE(CommonStatisticNames.OP_COPY_FROM_LOCAL_FILE),
+ OP_CREATE(CommonStatisticNames.OP_CREATE),
+ OP_CREATE_NON_RECURSIVE(CommonStatisticNames.OP_CREATE_NON_RECURSIVE),
+ OP_DELETE(CommonStatisticNames.OP_DELETE),
+ OP_EXISTS(CommonStatisticNames.OP_EXISTS),
+ OP_GET_CONTENT_SUMMARY(CommonStatisticNames.OP_GET_CONTENT_SUMMARY),
+ OP_GET_DELEGATION_TOKEN(CommonStatisticNames.OP_GET_DELEGATION_TOKEN),
+ OP_GET_FILE_CHECKSUM(CommonStatisticNames.OP_GET_FILE_CHECKSUM),
+ OP_GET_FILE_STATUS(CommonStatisticNames.OP_GET_FILE_STATUS),
+ OP_GET_STATUS(CommonStatisticNames.OP_GET_STATUS),
+ OP_GLOB_STATUS(CommonStatisticNames.OP_GLOB_STATUS),
+ OP_IS_FILE(CommonStatisticNames.OP_IS_FILE),
+ OP_IS_DIRECTORY(CommonStatisticNames.OP_IS_DIRECTORY),
+ OP_LIST_FILES(CommonStatisticNames.OP_LIST_FILES),
+ OP_LIST_LOCATED_STATUS(CommonStatisticNames.OP_LIST_LOCATED_STATUS),
+ OP_LIST_STATUS(CommonStatisticNames.OP_LIST_STATUS),
+ OP_MKDIRS(CommonStatisticNames.OP_MKDIRS),
+ OP_MODIFY_ACL_ENTRIES(CommonStatisticNames.OP_MODIFY_ACL_ENTRIES),
+ OP_OPEN(CommonStatisticNames.OP_OPEN),
+ OP_REMOVE_ACL(CommonStatisticNames.OP_REMOVE_ACL),
+ OP_REMOVE_ACL_ENTRIES(CommonStatisticNames.OP_REMOVE_ACL_ENTRIES),
+ OP_REMOVE_DEFAULT_ACL(CommonStatisticNames.OP_REMOVE_DEFAULT_ACL),
+ OP_RENAME(CommonStatisticNames.OP_RENAME),
+ OP_SET_ACL(CommonStatisticNames.OP_SET_ACL),
+ OP_SET_OWNER(CommonStatisticNames.OP_SET_OWNER),
+ OP_SET_PERMISSION(CommonStatisticNames.OP_SET_PERMISSION),
+ OP_SET_TIMES(CommonStatisticNames.OP_SET_TIMES),
+ OP_TRUNCATE(CommonStatisticNames.OP_TRUNCATE),
+
+ // counters below are not needed in production, as the scheme_countername expansion is taken care of by the
+ // FileSystemCounterGroup, the only reason they are here is that some analyzers still depend on them
+ @Deprecated
+ HDFS_BYTES_READ("hdfsBytesRead"),
+ @Deprecated
+ HDFS_BYTES_WRITTEN("hdfsBytesWritten"),
+ @Deprecated
+ FILE_BYTES_READ("fileBytesRead"),
+ @Deprecated
+ FILE_BYTES_WRITTEN("fileBytesWritten");
+
+ private final String opName;
+
+ FileSystemCounter(String opName) {
+ this.opName = opName;
+ }
+
+ public String getOpName() {
+ return opName;
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounterGroup.java b/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounterGroup.java
index 502415484a..76e5235d27 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounterGroup.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/FileSystemCounterGroup.java
@@ -27,11 +27,10 @@
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import com.google.common.base.Joiner;
-import static com.google.common.base.Preconditions.*;
-
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
@@ -225,12 +224,17 @@ public int size() {
}
@Override
- public void incrAllCounters(CounterGroupBase other) {
- if (checkNotNull(other.getUnderlyingGroup(), "other group")
+ public void incrAllCounters(CounterGroupBase rightGroup) {
+ aggrAllCounters(rightGroup);
+ }
+
+ @Override
+ public void aggrAllCounters(CounterGroupBase other) {
+ if (Objects.requireNonNull(other.getUnderlyingGroup(), "other group")
instanceof FileSystemCounterGroup>) {
for (TezCounter counter : other) {
FSCounter c = (FSCounter) ((TezCounter)counter).getUnderlyingCounter();
- findCounter(c.scheme, c.key) .increment(counter.getValue());
+ findCounter(c.scheme, c.key) .aggregate(counter);
}
}
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/FrameworkCounterGroup.java b/tez-api/src/main/java/org/apache/tez/common/counters/FrameworkCounterGroup.java
index 3a4aa9754e..cb27741283 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/FrameworkCounterGroup.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/FrameworkCounterGroup.java
@@ -18,13 +18,14 @@
package org.apache.tez.common.counters;
-import static com.google.common.base.Preconditions.checkNotNull;
+
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.io.WritableUtils;
@@ -190,14 +191,20 @@ public int size() {
return n;
}
+ @Override
+ @SuppressWarnings("deprecation")
+ public void incrAllCounters(CounterGroupBase rightGroup) {
+ aggrAllCounters(rightGroup);
+ }
+
@SuppressWarnings("rawtypes")
@Override
- public void incrAllCounters(CounterGroupBase other) {
- if (checkNotNull(other, "other counter group")
+ public void aggrAllCounters(CounterGroupBase other) {
+ if (Objects.requireNonNull(other, "other counter group")
instanceof FrameworkCounterGroup, ?>) {
for (TezCounter counter : other) {
findCounter(((FrameworkCounter) counter).key.name())
- .increment(counter.getValue());
+ .aggregate(counter);
}
}
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/Limits.java b/tez-api/src/main/java/org/apache/tez/common/counters/Limits.java
index 332df8e1e0..3e926c693b 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/Limits.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/Limits.java
@@ -30,33 +30,34 @@ public class Limits {
private static final Logger LOG = LoggerFactory.getLogger(Limits.class);
+ private static final Configuration DEFAULT_CONFIGURATION = new TezConfiguration();
private static Configuration conf = null;
private static int GROUP_NAME_MAX;
private static int COUNTER_NAME_MAX;
private static int GROUPS_MAX;
private static int COUNTERS_MAX;
- private static boolean initialized = false;
- private static synchronized void ensureInitialized() {
- if (initialized) {
- return;
- }
- if (conf == null) {
- conf = new TezConfiguration();
+ static {
+ init(DEFAULT_CONFIGURATION);
+ }
+
+ public synchronized static void setConfiguration(Configuration conf) {
+ // see change to reset()
+ if (Limits.conf == DEFAULT_CONFIGURATION && conf != null) {
+ init(conf);
}
- GROUP_NAME_MAX =
- conf.getInt(TezConfiguration.TEZ_COUNTERS_GROUP_NAME_MAX_LENGTH,
- TezConfiguration.TEZ_COUNTERS_GROUP_NAME_MAX_LENGTH_DEFAULT);
- COUNTER_NAME_MAX =
- conf.getInt(TezConfiguration.TEZ_COUNTERS_COUNTER_NAME_MAX_LENGTH,
- TezConfiguration.TEZ_COUNTERS_COUNTER_NAME_MAX_LENGTH_DEFAULT);
- GROUPS_MAX =
- conf.getInt(TezConfiguration.TEZ_COUNTERS_MAX_GROUPS,
- TezConfiguration.TEZ_COUNTERS_MAX_GROUPS_DEFAULT);
+ }
+
+ private static void init(Configuration conf) {
+ Limits.conf = conf;
+ GROUP_NAME_MAX = conf.getInt(TezConfiguration.TEZ_COUNTERS_GROUP_NAME_MAX_LENGTH,
+ TezConfiguration.TEZ_COUNTERS_GROUP_NAME_MAX_LENGTH_DEFAULT);
+ COUNTER_NAME_MAX = conf.getInt(TezConfiguration.TEZ_COUNTERS_COUNTER_NAME_MAX_LENGTH,
+ TezConfiguration.TEZ_COUNTERS_COUNTER_NAME_MAX_LENGTH_DEFAULT);
+ GROUPS_MAX = conf.getInt(TezConfiguration.TEZ_COUNTERS_MAX_GROUPS,
+ TezConfiguration.TEZ_COUNTERS_MAX_GROUPS_DEFAULT);
COUNTERS_MAX =
- conf.getInt(TezConfiguration.TEZ_COUNTERS_MAX,
- TezConfiguration.TEZ_COUNTERS_MAX_DEFAULT);
- initialized = true;
+ conf.getInt(TezConfiguration.TEZ_COUNTERS_MAX, TezConfiguration.TEZ_COUNTERS_MAX_DEFAULT);
LOG.info("Counter limits initialized with parameters: " + " GROUP_NAME_MAX=" + GROUP_NAME_MAX
+ ", MAX_GROUPS=" + GROUPS_MAX + ", COUNTER_NAME_MAX=" + COUNTER_NAME_MAX
+ ", MAX_COUNTERS=" + COUNTERS_MAX);
@@ -70,17 +71,14 @@ public static String filterName(String name, int maxLen) {
}
public static String filterCounterName(String name) {
- ensureInitialized();
return filterName(name, COUNTER_NAME_MAX);
}
public static String filterGroupName(String name) {
- ensureInitialized();
return filterName(name, GROUP_NAME_MAX);
}
public synchronized void checkCounters(int size) {
- ensureInitialized();
if (firstViolation != null) {
throw new LimitExceededException(firstViolation);
}
@@ -97,7 +95,6 @@ public synchronized void incrCounters() {
}
public synchronized void checkGroups(int size) {
- ensureInitialized();
if (firstViolation != null) {
throw new LimitExceededException(firstViolation);
}
@@ -107,21 +104,10 @@ public synchronized void checkGroups(int size) {
}
}
- public synchronized LimitExceededException violation() {
- return firstViolation;
- }
-
- public synchronized static void setConfiguration(Configuration conf) {
- if (Limits.conf == null && conf != null) {
- Limits.conf = conf;
- }
- }
-
@VisibleForTesting
@InterfaceAudience.Private
public synchronized static void reset() {
- conf = null;
- initialized = false;
+ conf = DEFAULT_CONFIGURATION;
}
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/TaskCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/TaskCounter.java
index 2f18bc677b..19d5bbdffa 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/TaskCounter.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/TaskCounter.java
@@ -21,10 +21,11 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
// Counters used by Task classes
+// Keep in sync with tez-ui/src/main/webapp/config/default-app-conf.js
@Private
public enum TaskCounter {
// TODO Eventually, rename counters to be non-MR specific and map them to MR equivalent.
-
+
NUM_SPECULATIONS,
/**
@@ -38,29 +39,29 @@ public enum TaskCounter {
* Alternately number of records seen by a ReduceProcessor
*/
REDUCE_INPUT_RECORDS,
-
+
REDUCE_OUTPUT_RECORDS, // Not used at the moment.
REDUCE_SKIPPED_GROUPS, // Not used at the moment.
REDUCE_SKIPPED_RECORDS, // Not used at the moment.
SPLIT_RAW_BYTES,
-
+
COMBINE_INPUT_RECORDS,
COMBINE_OUTPUT_RECORDS, // Not used at the moment.
/**
* Number of records written to disk in case of OnFileSortedOutput.
- *
- * Number of additional records writtent out to disk in case of
+ *
+ * Number of additional records written out to disk in case of
* ShuffledMergedInput; this represents the number of unnecessary spills to
* disk caused by lac of memory.
*/
SPILLED_RECORDS,
/**
- * Number of Inputs from which data is copied. Represents physical Inputs.
+ * Number of Inputs from which data is copied. Represents physical Inputs.
*/
NUM_SHUFFLED_INPUTS,
-
+
/**
* Number of Inputs from which data was not copied - typically due to an empty Input
*/
@@ -70,10 +71,12 @@ public enum TaskCounter {
* Number of failed copy attempts (physical inputs)
*/
NUM_FAILED_SHUFFLE_INPUTS,
-
+
MERGED_MAP_OUTPUTS,
GC_TIME_MILLIS,
CPU_MILLISECONDS,
+ /** Wall clock time taken by the task initialization and execution. */
+ WALL_CLOCK_MILLISECONDS,
PHYSICAL_MEMORY_BYTES,
VIRTUAL_MEMORY_BYTES,
COMMITTED_HEAP_BYTES,
@@ -81,7 +84,7 @@ public enum TaskCounter {
/**
* Represents the number of Input Records that were actually processed.
* Used by MRInput and ShuffledUnorderedKVInput
- *
+ *
*/
INPUT_RECORDS_PROCESSED,
@@ -90,19 +93,26 @@ public enum TaskCounter {
*/
INPUT_SPLIT_LENGTH_BYTES,
- //
+ //
/**
* Represents the number of actual output records.
* Used by MROutput, OnFileSortedOutput, and OnFileUnorderedKVOutput
*/
OUTPUT_RECORDS,
-
+
+ /**
+ * Approximate number of input records that should be processed as the event keeps arriving from
+ * inputs.
+ * //TODO: As of now supporting broadcast data only.
+ */
+ APPROXIMATE_INPUT_RECORDS,
+
/**
* Represent the number of large records in the output - typically, records which are
* spilled directly
*/
OUTPUT_LARGE_RECORDS,
-
+
SKIPPED_RECORDS, // Not used at the moment.
/**
@@ -122,19 +132,19 @@ public enum TaskCounter {
* size + overhead)
*/
OUTPUT_BYTES_PHYSICAL,
-
+
/**
* Bytes written to disk due to unnecessary spills (lac of adequate memory).
* Used by OnFileSortedOutput and ShuffledMergedInput
*/
ADDITIONAL_SPILLS_BYTES_WRITTEN,
-
+
/**
* Bytes read from disk due to previous spills (lac of adequate memory).
* Used by OnFileSortedOutput and ShuffledMergedInput
*/
ADDITIONAL_SPILLS_BYTES_READ,
-
+
/**
* Spills that were generated & read by the same task (unnecessary spills due to lac of
* adequate memory).
@@ -149,7 +159,7 @@ public enum TaskCounter {
* as final merge is avoided.
*/
SHUFFLE_CHUNK_COUNT,
-
+
INPUT_GROUPS, // Not used at the moment. Will eventually replace REDUCE_INPUT_GROUPS
/**
@@ -162,15 +172,15 @@ public enum TaskCounter {
* Uncompressed size of the data being processed by the relevant Shuffle.
* Includes serialization, file format etc overheads.
*/
- SHUFFLE_BYTES_DECOMPRESSED,
+ SHUFFLE_BYTES_DECOMPRESSED,
/**
- * Number of bytes which were shuffled directly to memory.
+ * Number of bytes which were shuffled directly to memory.
*/
SHUFFLE_BYTES_TO_MEM,
/**
- * Number of bytes which were shuffled directly to disk
+ * Number of bytes which were shuffled directly to disk
*/
SHUFFLE_BYTES_TO_DISK,
@@ -218,5 +228,13 @@ public enum TaskCounter {
*
* Represented in milliseconds
*/
- LAST_EVENT_RECEIVED
+ LAST_EVENT_RECEIVED,
+
+
+ /**
+ * The size of the data that is transmitted via event.
+ *
+ * Represented in number of bytes
+ */
+ DATA_BYTES_VIA_EVENT
}
\ No newline at end of file
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/TezCounter.java b/tez-api/src/main/java/org/apache/tez/common/counters/TezCounter.java
index 2b40ed2dbc..9abbb82167 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/TezCounter.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/TezCounter.java
@@ -73,10 +73,18 @@ public interface TezCounter extends Writable {
* @param incr the value to increase this counter by
*/
void increment(long incr);
-
+
+ /**
+ * Aggregate this counter with another counter
+ * @param other TezCounter to aggregate with, by default this is incr(other.getValue())
+ */
+ public default void aggregate(TezCounter other) {
+ increment(other.getValue());
+ };
+
/**
* Return the underlying object if this is a facade.
- * @return the undelying object.
+ * @return the underlying object.
*/
@Private
TezCounter getUnderlyingCounter();
diff --git a/tez-api/src/main/java/org/apache/tez/common/counters/TezCounters.java b/tez-api/src/main/java/org/apache/tez/common/counters/TezCounters.java
index ca03f415ba..a1205b9fdd 100644
--- a/tez-api/src/main/java/org/apache/tez/common/counters/TezCounters.java
+++ b/tez-api/src/main/java/org/apache/tez/common/counters/TezCounters.java
@@ -128,7 +128,17 @@ protected CounterGroup newFileSystemGroup() {
* Default constructor
*/
public TezCounters() {
- super(groupFactory);
+ this(groupFactory);
+ }
+
+ /**
+ * Construct the Counters object from the another counters object
+ * @param the type of counter
+ * @param the type of counter group
+ */
+ public > TezCounters(
+ CounterGroupFactory customGroupFactory) {
+ super(customGroupFactory);
}
/**
diff --git a/tez-api/src/main/java/org/apache/tez/common/security/HistoryACLPolicyManager.java b/tez-api/src/main/java/org/apache/tez/common/security/HistoryACLPolicyManager.java
index 92eea67440..cb4efc6fb6 100644
--- a/tez-api/src/main/java/org/apache/tez/common/security/HistoryACLPolicyManager.java
+++ b/tez-api/src/main/java/org/apache/tez/common/security/HistoryACLPolicyManager.java
@@ -30,7 +30,7 @@
/**
* ACL Policy Manager
- * An instance of this implements any ACL related activity when starting a session or submitting a
+ * An instance of this implements any ACL related activity when starting a session or submitting a
* DAG. It is used in the HistoryLoggingService to create domain ids and populate entities with
* domain id.
*/
@@ -41,7 +41,7 @@ public interface HistoryACLPolicyManager extends Configurable {
/**
* Take any necessary steps for setting up both Session ACLs and non session acls. This is called
* with the am configuration which contains the ACL information to be used to create a domain.
- * If the method returns a value, then its assumed to be a valid domain and used as domainId.
+ * If the method returns a value, then it's assumed to be a valid domain and used as domainId.
* If the method returns null, acls are disabled at session level, i.e use default acls at session
* level.
* If the method throws an Exception, history logging is disabled for the entire session.
diff --git a/tez-api/src/main/java/org/apache/tez/common/security/Master.java b/tez-api/src/main/java/org/apache/tez/common/security/Master.java
index de73d10092..d0b8d16c47 100644
--- a/tez-api/src/main/java/org/apache/tez/common/security/Master.java
+++ b/tez-api/src/main/java/org/apache/tez/common/security/Master.java
@@ -29,12 +29,14 @@
@Private
@Unstable
-public class Master {
+public final class Master {
public enum State {
- INITIALIZING, RUNNING;
+ INITIALIZING, RUNNING
}
+ private Master() {}
+
public static String getMasterUserName(Configuration conf) {
return conf.get(YarnConfiguration.RM_PRINCIPAL);
}
diff --git a/tez-api/src/main/java/org/apache/tez/common/security/TokenCache.java b/tez-api/src/main/java/org/apache/tez/common/security/TokenCache.java
index fc2c07dc1c..21b1026d39 100644
--- a/tez-api/src/main/java/org/apache/tez/common/security/TokenCache.java
+++ b/tez-api/src/main/java/org/apache/tez/common/security/TokenCache.java
@@ -34,6 +34,7 @@
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
+import org.apache.tez.dag.api.TezConfiguration;
/**
@@ -44,14 +45,16 @@
*/
@InterfaceAudience.Private
@InterfaceStability.Unstable
-public class TokenCache {
+public final class TokenCache {
private static final Logger LOG = LoggerFactory.getLogger(TokenCache.class);
+ private TokenCache() {}
+
/**
* auxiliary method to get user's secret keys..
- * @param alias
+ *
* @return secret key from the storage
*/
public static byte[] getSecretKey(Credentials credentials, Text alias) {
@@ -63,10 +66,9 @@ public static byte[] getSecretKey(Credentials credentials, Text alias) {
/**
* Convenience method to obtain delegation tokens from namenodes
* corresponding to the paths passed.
- * @param credentials
+ * @param credentials credentials
* @param ps array of paths
* @param conf configuration
- * @throws IOException
*/
public static void obtainTokensForFileSystems(Credentials credentials,
Path[] ps, Configuration conf) throws IOException {
@@ -79,7 +81,7 @@ public static void obtainTokensForFileSystems(Credentials credentials,
private static final int MAX_FS_OBJECTS = 10;
static void obtainTokensForFileSystemsInternal(Credentials credentials,
Path[] ps, Configuration conf) throws IOException {
- Set fsSet = new HashSet();
+ Set fsSet = new HashSet<>();
boolean limitExceeded = false;
for(Path p: ps) {
FileSystem fs = p.getFileSystem(conf);
@@ -101,24 +103,37 @@ static void obtainTokensForFileSystemsInternal(Credentials credentials,
}
}
+ static boolean isTokenRenewalExcluded(FileSystem fs, Configuration conf) {
+ String[] nns =
+ conf.getStrings(TezConfiguration.TEZ_JOB_FS_SERVERS_TOKEN_RENEWAL_EXCLUDE);
+ if (nns != null) {
+ String host = fs.getUri().getHost();
+ for (String nn : nns) {
+ if (nn.equals(host)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* get delegation token for a specific FS
- * @param fs
- * @param credentials
- * @param p
- * @param conf
- * @throws IOException
*/
static void obtainTokensForFileSystemsInternal(FileSystem fs,
Credentials credentials, Configuration conf) throws IOException {
// TODO Change this to use YARN utilities once YARN-1664 is fixed.
- String delegTokenRenewer = Master.getMasterPrincipal(conf);
- if (delegTokenRenewer == null || delegTokenRenewer.length() == 0) {
- throw new IOException(
- "Can't get Master Kerberos principal for use as renewer");
+ // RM skips renewing token with empty renewer
+ String delegTokenRenewer = "";
+ if (!isTokenRenewalExcluded(fs, conf)) {
+ delegTokenRenewer = Master.getMasterPrincipal(conf);
+ if (delegTokenRenewer == null || delegTokenRenewer.length() == 0) {
+ throw new IOException(
+ "Can't get Master Kerberos principal for use as renewer");
+ }
}
- final Token> tokens[] = fs.addDelegationTokens(delegTokenRenewer,
+ final Token>[] tokens = fs.addDelegationTokens(delegTokenRenewer,
credentials);
if (tokens != null) {
for (Token> token : tokens) {
@@ -131,7 +146,6 @@ static void obtainTokensForFileSystemsInternal(FileSystem fs,
/**
* store session specific token
- * @param t
*/
@InterfaceAudience.Private
public static void setSessionToken(Token extends TokenIdentifier> t,
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java b/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java
index cdfa3b2488..0864b82e80 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java
@@ -33,6 +33,7 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
+import java.util.Objects;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualLinkedHashBidiMap;
@@ -41,6 +42,7 @@
import org.apache.hadoop.yarn.util.ConverterUtils;
import org.apache.tez.client.CallerContext;
import org.apache.tez.common.JavaOptsChecker;
+import org.apache.tez.common.TezUtils;
import org.apache.tez.dag.api.Vertex.VertexExecutionContext;
import org.apache.tez.dag.api.records.DAGProtos;
import org.apache.tez.serviceplugins.api.ServicePluginsDescriptor;
@@ -72,22 +74,22 @@
import org.apache.tez.dag.api.records.DAGProtos.VertexPlan;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
- * Top level entity that defines the DAG (Directed Acyclic Graph) representing
- * the data flow graph. Consists of a set of Vertices and Edges connecting the
- * vertices. Vertices represent transformations of data and edges represent
+ * Top level entity that defines the DAG (Directed Acyclic Graph) representing
+ * the data flow graph. Consists of a set of Vertices and Edges connecting the
+ * vertices. Vertices represent transformations of data and edges represent
* movement of data between vertices.
*/
@Public
public class DAG {
-
+
private static final Logger LOG = LoggerFactory.getLogger(DAG.class);
-
+
final BidiMap vertices =
new DualLinkedHashBidiMap();
final Set edges = Sets.newHashSet();
@@ -127,11 +129,11 @@ public static DAG create(String name) {
* @return {@link DAG}
*/
public synchronized DAG addTaskLocalFiles(Map localFiles) {
- Preconditions.checkNotNull(localFiles);
+ Objects.requireNonNull(localFiles);
TezCommonUtils.addAdditionalLocalResources(localFiles, commonTaskLocalFiles, "DAG " + getName());
return this;
}
-
+
public synchronized DAG addVertex(Vertex vertex) {
if (vertices.containsKey(vertex.getName())) {
throw new IllegalStateException(
@@ -144,18 +146,18 @@ public synchronized DAG addVertex(Vertex vertex) {
public synchronized Vertex getVertex(String vertexName) {
return vertices.get(vertexName);
}
-
+
/**
* One of the methods that can be used to provide information about required
* Credentials when running on a secure cluster. A combination of this and
* addURIsForCredentials should be used to specify information about all
* credentials required by a DAG. AM specific credentials are not used when
* executing a DAG.
- *
+ *
* Set credentials which will be required to run this dag. This method can be
* used if the client has already obtained some or all of the required
* credentials.
- *
+ *
* @param credentials Credentials for the DAG
* @return {@link DAG}
*/
@@ -177,7 +179,7 @@ public synchronized DAG setCredentials(Credentials credentials) {
*/
@Deprecated
public synchronized DAG setDAGInfo(String dagInfo) {
- Preconditions.checkNotNull(dagInfo);
+ Objects.requireNonNull(dagInfo);
this.dagInfo = dagInfo;
return this;
}
@@ -189,13 +191,13 @@ public synchronized DAG setDAGInfo(String dagInfo) {
* @return {@link DAG}
*/
public synchronized DAG setCallerContext(CallerContext callerContext) {
- Preconditions.checkNotNull(callerContext);
+ Objects.requireNonNull(callerContext);
this.callerContext = callerContext;
return this;
}
/**
- * Create a group of vertices that share a common output. This can be used to implement
+ * Create a group of vertices that share a common output. This can be used to implement
* unions efficiently.
* @param name Name of the group.
* @param members {@link Vertex} members of the group
@@ -242,27 +244,27 @@ public synchronized DAGAccessControls getDagAccessControls() {
* setCredentials should be used to specify information about all credentials
* required by a DAG. AM specific credentials are not used when executing a
* DAG.
- *
+ *
* This method can be used to specify a list of URIs for which Credentials
* need to be obtained so that the job can run. An incremental list of URIs
* can be provided by making multiple calls to the method.
- *
+ *
* Currently, @{link credentials} can only be fetched for HDFS and other
* {@link org.apache.hadoop.fs.FileSystem} implementations that support
* credentials.
- *
+ *
* @param uris
* a list of {@link URI}s
* @return {@link DAG}
*/
public synchronized DAG addURIsForCredentials(Collection uris) {
- Preconditions.checkNotNull(uris, "URIs cannot be null");
+ Objects.requireNonNull(uris, "URIs cannot be null");
urisForCredentials.addAll(uris);
return this;
}
/**
- *
+ *
* @return an unmodifiable list representing the URIs for which credentials
* are required.
*/
@@ -270,7 +272,7 @@ public synchronized DAG addURIsForCredentials(Collection uris) {
public synchronized Collection getURIsForCredentials() {
return Collections.unmodifiableCollection(urisForCredentials);
}
-
+
@Private
public synchronized Set getVertices() {
return Collections.unmodifiableSet(this.vertices.values());
@@ -303,7 +305,7 @@ public synchronized DAG addEdge(Edge edge) {
edges.add(edge);
return this;
}
-
+
/**
* Add a {@link GroupInputEdge} to the DAG.
* @param edge {@link GroupInputEdge}
@@ -327,7 +329,7 @@ public synchronized DAG addEdge(GroupInputEdge edge) {
VertexGroup av = edge.getInputVertexGroup();
av.addOutputVertex(edge.getOutputVertex(), edge);
groupInputEdges.add(edge);
-
+
// add new edge between members of VertexGroup and destVertex of the GroupInputEdge
List newEdges = Lists.newLinkedList();
Vertex dstVertex = edge.getOutputVertex();
@@ -336,14 +338,14 @@ public synchronized DAG addEdge(GroupInputEdge edge) {
newEdges.add(Edge.create(member, dstVertex, edge.getEdgeProperty()));
}
dstVertex.addGroupInput(uv.getGroupName(), uv.getGroupInfo());
-
+
for (Edge e : newEdges) {
addEdge(e);
}
-
+
return this;
}
-
+
/**
* Get the DAG name
* @return DAG name
@@ -432,7 +434,7 @@ void checkAndInferOneToOneParallelism() {
newKnownTasksVertices.add(vertex);
}
}
-
+
// walk through all known source 1-1 edges and infer parallelism
// add newly inferred vertices for consideration as known sources
// the outer loop will run for every new level of inferring the parallelism
@@ -455,19 +457,19 @@ void checkAndInferOneToOneParallelism() {
}
}
}
-
+
// check for inconsistency and errors
for (Edge e : edges) {
Vertex inputVertex = e.getInputVertex();
Vertex outputVertex = e.getOutputVertex();
-
+
if (e.getEdgeProperty().getDataMovementType() == DataMovementType.ONE_TO_ONE) {
if (inputVertex.getParallelism() != outputVertex.getParallelism()) {
// both should be equal or equal to -1.
if (outputVertex.getParallelism() != -1) {
throw new TezUncheckedException(
"1-1 Edge. Destination vertex parallelism must match source vertex. "
- + "Vertex: " + inputVertex.getName() + " does not match vertex: "
+ + "Vertex: " + inputVertex.getName() + " does not match vertex: "
+ outputVertex.getName());
}
}
@@ -526,7 +528,7 @@ void checkAndInferOneToOneParallelism() {
}
}
}
-
+
// AnnotatedVertex is used by verify()
private static class AnnotatedVertex {
Vertex v;
@@ -572,7 +574,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
if (vertices.isEmpty()) {
throw new IllegalStateException("Invalid dag containing 0 vertices");
}
-
+
// check for valid vertices, duplicate vertex names,
// and prepare for cycle detection
Map vertexMap = new HashMap();
@@ -590,14 +592,14 @@ Deque verify(boolean restricted) throws IllegalStateException {
for (Edge e : edges) {
// Construct structure for cycle detection
Vertex inputVertex = e.getInputVertex();
- Vertex outputVertex = e.getOutputVertex();
+ Vertex outputVertex = e.getOutputVertex();
List edgeList = edgeMap.get(inputVertex);
if (edgeList == null) {
edgeList = new ArrayList();
edgeMap.put(inputVertex, edgeList);
}
edgeList.add(e);
-
+
// Construct map for Input name verification
Set inboundSet = inboundVertexMap.get(outputVertex);
if (inboundSet == null) {
@@ -605,7 +607,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
inboundVertexMap.put(outputVertex, inboundSet);
}
inboundSet.add(inputVertex.getName());
-
+
// Construct map for Output name verification
Set outboundSet = outboundVertexMap.get(inputVertex);
if (outboundSet == null) {
@@ -617,7 +619,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
// check input and output names don't collide with vertex names
for (Vertex vertex : vertices.values()) {
- for (RootInputLeafOutput
+ for (RootInputLeafOutput
input : vertex.getInputs()) {
if (vertexMap.containsKey(input.getName())) {
throw new IllegalStateException("Vertex: "
@@ -626,7 +628,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
+ input.getName());
}
}
- for (RootInputLeafOutput
+ for (RootInputLeafOutput
output : vertex.getOutputs()) {
if (vertexMap.containsKey(output.getName())) {
throw new IllegalStateException("Vertex: "
@@ -640,7 +642,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
// Check for valid InputNames
for (Entry> entry : inboundVertexMap.entrySet()) {
Vertex vertex = entry.getKey();
- for (RootInputLeafOutput
+ for (RootInputLeafOutput
input : vertex.getInputs()) {
if (entry.getValue().contains(input.getName())) {
throw new IllegalStateException("Vertex: "
@@ -654,7 +656,7 @@ Deque verify(boolean restricted) throws IllegalStateException {
// Check for valid OutputNames
for (Entry> entry : outboundVertexMap.entrySet()) {
Vertex vertex = entry.getKey();
- for (RootInputLeafOutput
+ for (RootInputLeafOutput
output : vertex.getOutputs()) {
if (entry.getValue().contains(output.getName())) {
throw new IllegalStateException("Vertex: "
@@ -664,8 +666,8 @@ Deque verify(boolean restricted) throws IllegalStateException {
}
}
}
-
-
+
+
// Not checking for repeated input names / output names vertex names on the same vertex,
// since we only allow 1 at the moment.
// When additional inputs are supported, this can be chceked easily (and early)
@@ -677,16 +679,12 @@ Deque verify(boolean restricted) throws IllegalStateException {
if (restricted) {
for (Edge e : edges) {
- if (e.getEdgeProperty().getDataSourceType() !=
- DataSourceType.PERSISTED) {
+ DataSourceType dataSourceType = e.getEdgeProperty().getDataSourceType();
+ if (dataSourceType != DataSourceType.PERSISTED &&
+ dataSourceType != DataSourceType.EPHEMERAL) {
throw new IllegalStateException(
"Unsupported source type on edge. " + e);
}
- if (e.getEdgeProperty().getSchedulingType() !=
- SchedulingType.SEQUENTIAL) {
- throw new IllegalStateException(
- "Unsupported scheduling type on edge. " + e);
- }
}
}
@@ -877,13 +875,13 @@ public synchronized DAGPlan createDag(Configuration tezConf, Credentials extraCr
groupBuilder.addGroupMembers(v.getName());
}
groupBuilder.addAllOutputs(groupInfo.outputs);
- for (Map.Entry entry :
+ for (Map.Entry entry :
groupInfo.edgeMergedInputs.entrySet()) {
groupBuilder.addEdgeMergedInputs(
PlanGroupInputEdgeInfo.newBuilder().setDestVertexName(entry.getKey()).
setMergedInput(DagTypeConverters.convertToDAGPlan(entry.getValue())));
}
- dagBuilder.addVertexGroups(groupBuilder);
+ dagBuilder.addVertexGroups(groupBuilder);
}
}
@@ -955,7 +953,7 @@ public synchronized DAGPlan createDag(Configuration tezConf, Credentials extraCr
dagCredentials.addAll(dataSink.getCredentials());
}
}
-
+
VertexPlan.Builder vertexBuilder = VertexPlan.newBuilder();
vertexBuilder.setName(vertex.getName());
vertexBuilder.setType(PlanVertexType.NORMAL); // vertex type is implicitly NORMAL until TEZ-46.
@@ -985,12 +983,7 @@ public synchronized DAGPlan createDag(Configuration tezConf, Credentials extraCr
if (vertex.getConf()!= null && vertex.getConf().size() > 0) {
ConfigurationProto.Builder confBuilder = ConfigurationProto.newBuilder();
- for (Map.Entry entry : vertex.getConf().entrySet()) {
- PlanKeyValuePair.Builder keyValueBuilder = PlanKeyValuePair.newBuilder();
- keyValueBuilder.setKey(entry.getKey());
- keyValueBuilder.setValue(entry.getValue());
- confBuilder.addConfKeyValues(keyValueBuilder);
- }
+ TezUtils.populateConfProtoFromEntries(vertex.getConf().entrySet(), confBuilder);
vertexBuilder.setVertexConf(confBuilder);
}
@@ -1049,7 +1042,7 @@ public synchronized DAGPlan createDag(Configuration tezConf, Credentials extraCr
}
}
}
-
+
if (vertex.getVertexManagerPlugin() != null) {
vertexBuilder.setVertexManagerPlugin(DagTypeConverters
.convertToDAGPlan(vertex.getVertexManagerPlugin()));
@@ -1091,12 +1084,7 @@ public synchronized DAGPlan createDag(Configuration tezConf, Credentials extraCr
ConfigurationProto.Builder confProtoBuilder = ConfigurationProto.newBuilder();
if (!this.dagConf.isEmpty()) {
- for (Entry entry : this.dagConf.entrySet()) {
- PlanKeyValuePair.Builder kvp = PlanKeyValuePair.newBuilder();
- kvp.setKey(entry.getKey());
- kvp.setValue(entry.getValue());
- confProtoBuilder.addConfKeyValues(kvp);
- }
+ TezUtils.populateConfProtoFromEntries(this.dagConf.entrySet(), confProtoBuilder);
}
// Copy historyLogLevel from tezConf into dagConf if its not overridden in dagConf.
String logLevel = this.dagConf.get(TezConfiguration.TEZ_HISTORY_LOGGING_LOGLEVEL);
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/DAGNotRunningException.java b/tez-api/src/main/java/org/apache/tez/dag/api/DAGNotRunningException.java
index cbc93a9647..93f5d71b53 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/DAGNotRunningException.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/DAGNotRunningException.java
@@ -21,7 +21,8 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
/**
- * Checked Exception thrown upon error
+ * Thrown by the AM when the DAG for which the status was queried
+ * is not running anymore: client can decide further action in this case.
*/
@Private
public class DAGNotRunningException extends TezException {
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/DagTypeConverters.java b/tez-api/src/main/java/org/apache/tez/dag/api/DagTypeConverters.java
index c5d9c0b4f7..a55e45a7fd 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/DagTypeConverters.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/DagTypeConverters.java
@@ -90,7 +90,9 @@
import org.apache.tez.serviceplugins.api.ServicePluginsDescriptor;
@Private
-public class DagTypeConverters {
+public final class DagTypeConverters {
+
+ private DagTypeConverters() {}
public static PlanLocalResourceVisibility convertToDAGPlan(LocalResourceVisibility visibility){
switch(visibility){
@@ -624,23 +626,24 @@ public static TezCountersProto convertTezCountersToProto(
}
public static DAGProtos.StatusGetOptsProto convertStatusGetOptsToProto(
- StatusGetOpts statusGetOpts) {
+ StatusGetOpts statusGetOpts) {
switch (statusGetOpts) {
- case GET_COUNTERS:
- return DAGProtos.StatusGetOptsProto.GET_COUNTERS;
+ case GET_COUNTERS:
+ return DAGProtos.StatusGetOptsProto.GET_COUNTERS;
+ case GET_MEMORY_USAGE:
+ return DAGProtos.StatusGetOptsProto.GET_MEMORY_USAGE;
}
- throw new TezUncheckedException("Could not convert StatusGetOpts to"
- + " proto");
+ throw new TezUncheckedException("Could not convert StatusGetOpts to" + " proto");
}
- public static StatusGetOpts convertStatusGetOptsFromProto(
- DAGProtos.StatusGetOptsProto proto) {
+ public static StatusGetOpts convertStatusGetOptsFromProto(DAGProtos.StatusGetOptsProto proto) {
switch (proto) {
- case GET_COUNTERS:
- return StatusGetOpts.GET_COUNTERS;
+ case GET_COUNTERS:
+ return StatusGetOpts.GET_COUNTERS;
+ case GET_MEMORY_USAGE:
+ return StatusGetOpts.GET_MEMORY_USAGE;
}
- throw new TezUncheckedException("Could not convert to StatusGetOpts from"
- + " proto");
+ throw new TezUncheckedException("Could not convert to StatusGetOpts from" + " proto");
}
public static List convertStatusGetOptsToProto(
@@ -735,7 +738,7 @@ public static ByteBuffer convertFromTezUserPayload(@Nullable UserPayload payload
if (payload == null) {
return null;
}
- return payload.getPayload();
+ return payload.getRawPayload();
}
public static VertexExecutionContextProto convertToProto(
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/DataSinkDescriptor.java b/tez-api/src/main/java/org/apache/tez/dag/api/DataSinkDescriptor.java
index 4d0d615db4..fec2bf6eed 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/DataSinkDescriptor.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/DataSinkDescriptor.java
@@ -21,13 +21,13 @@
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
+import java.util.Objects;
import javax.annotation.Nullable;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.security.Credentials;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
/**
@@ -121,7 +121,7 @@ public OutputDescriptor getOutputDescriptor() {
* @return this
*/
public synchronized DataSinkDescriptor addURIsForCredentials(Collection uris) {
- Preconditions.checkNotNull(uris, "URIs cannot be null");
+ Objects.requireNonNull(uris, "URIs cannot be null");
urisForCredentials.addAll(uris);
return this;
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/DataSourceDescriptor.java b/tez-api/src/main/java/org/apache/tez/dag/api/DataSourceDescriptor.java
index 1c5c16db5f..db43c91f7a 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/DataSourceDescriptor.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/DataSourceDescriptor.java
@@ -24,6 +24,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceAudience.Private;
@@ -34,7 +35,6 @@
import org.apache.tez.runtime.api.InputInitializer;
import org.apache.tez.runtime.api.events.InputDataInformationEvent;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
/**
@@ -157,7 +157,7 @@ public InputDescriptor getInputDescriptor() {
* @return this
*/
public synchronized DataSourceDescriptor addURIsForCredentials(Collection uris) {
- Preconditions.checkNotNull(uris, "URIs cannot be null");
+ Objects.requireNonNull(uris, "URIs cannot be null");
urisForCredentials.addAll(uris);
return this;
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/EdgeManagerPluginOnDemand.java b/tez-api/src/main/java/org/apache/tez/dag/api/EdgeManagerPluginOnDemand.java
index 3d7f2ab2b7..be58354c67 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/EdgeManagerPluginOnDemand.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/EdgeManagerPluginOnDemand.java
@@ -32,8 +32,8 @@
import org.apache.tez.runtime.api.events.InputReadErrorEvent;
/**
- * This interface defines the routing of the event between tasks of producer and
- * consumer vertices. The routing is bi-directional. Users can customize the
+ * This interface defines the routing of the event between tasks of producer and
+ * consumer vertices. The routing is bidirectional. Users can customize the
* routing by providing an implementation of this interface.
*/
@Public
@@ -70,22 +70,22 @@ public int getSource() {
/**
* Class to provide routing metadata for {@link Event}s to be routed between
- * producer and consumer tasks. The routing data enabled the system to send
+ * producer and consumer tasks. The routing data enabled the system to send
* the event from the producer task output to the consumer task input
*/
public static class EventRouteMetadata {
private final int numEvents;
private final int[] targetIndices;
private final int[] sourceIndices;
-
+
/**
* Create an {@link EventRouteMetadata} that will create numEvents copies of
* the {@link Event} to be routed. Use this to create
* {@link EventRouteMetadata} for {@link DataMovementEvent}s or
* {@link InputFailedEvent}s where the target input indices must be
- * specified to route those events. Typically numEvents would be 1 for these
+ * specified to route those events. Typically, numEvents would be 1 for these
* events.
- *
+ *
* @param numEvents
* Number of copies of the event to be routed
* @param targetIndices
@@ -97,14 +97,14 @@ public static class EventRouteMetadata {
public static EventRouteMetadata create(int numEvents, int[] targetIndices) {
return new EventRouteMetadata(numEvents, targetIndices, null);
}
-
+
/**
* Create an {@link EventRouteMetadata} that will create numEvents copies of
* the {@link Event} to be routed. Use this to create
* {@link EventRouteMetadata} for {@link CompositeDataMovementEvent} where
* the target input indices and source output indices must be specified to
- * route those events. Typically numEvents would be 1 for these events.
- *
+ * route those events. Typically, numEvents would be 1 for these events.
+ *
* @param numEvents
* Number of copies of the event to be routed
* @param targetIndices
@@ -157,7 +157,7 @@ public int getNumEvents() {
* extending this to create a {@link EdgeManagerPluginOnDemand}, must provide
* the same constructor so that Tez can create an instance of the class at
* runtime.
- *
+ *
* @param context
* the context within which this {@link EdgeManagerPluginOnDemand}
* will run. Includes information like configuration which the user
@@ -177,7 +177,7 @@ public EdgeManagerPluginOnDemand(EdgeManagerPluginContext context) {
* @throws Exception
*/
public abstract void initialize() throws Exception;
-
+
/**
* This method will be invoked just before routing of events will begin. The
* plugin can use this opportunity to make any runtime initialization's that
@@ -187,7 +187,7 @@ public EdgeManagerPluginOnDemand(EdgeManagerPluginContext context) {
/**
* Get the number of physical inputs on the destination task
- * @param destinationTaskIndex Index of destination task for which number of
+ * @param destinationTaskIndex Index of destination task for which number of
* inputs is needed
* @return Number of physical inputs on the destination task
* @throws Exception
@@ -196,34 +196,34 @@ public EdgeManagerPluginOnDemand(EdgeManagerPluginContext context) {
/**
* Get the number of physical outputs on the source task
- * @param sourceTaskIndex Index of the source task for which number of outputs
+ * @param sourceTaskIndex Index of the source task for which number of outputs
* is needed
* @return Number of physical outputs on the source task
* @throws Exception
*/
public abstract int getNumSourceTaskPhysicalOutputs(int sourceTaskIndex) throws Exception;
-
+
/**
* Get the number of destination tasks that consume data from the source task
* @param sourceTaskIndex Source task index
* @throws Exception
*/
public abstract int getNumDestinationConsumerTasks(int sourceTaskIndex) throws Exception;
-
+
/**
* Return the source task index to which to send the input error event
- *
+ *
* @param destinationTaskIndex
* Destination task that reported the error
* @param destinationFailedInputIndex
- * Index of the physical input on the destination task that reported
+ * Index of the physical input on the destination task that reported
* the error
* @return Index of the source task that created the unavailable input
* @throws Exception
*/
public abstract int routeInputErrorEventToSource(int destinationTaskIndex,
int destinationFailedInputIndex) throws Exception;
-
+
/**
* The method provides the {@link EventRouteMetadata} to route a
* {@link DataMovementEvent} produced by the given source task to the given
@@ -231,7 +231,7 @@ public abstract int routeInputErrorEventToSource(int destinationTaskIndex,
* target input indices set to enable the routing. If the routing metadata is
* common across different events then the plugin can cache and reuse the same
* object.
- *
+ *
* @param sourceTaskIndex
* The index of the task in the source vertex of this edge that
* produced a {@link DataMovementEvent}
@@ -254,7 +254,7 @@ public abstract int routeInputErrorEventToSource(int destinationTaskIndex,
* the target input indices and source output indices set to enable the
* routing. If the routing metadata is common across different events then the
* plugin can cache and reuse the same object.
- *
+ *
* @param sourceTaskIndex
* The index of the task in the source vertex of this edge that
* produced a {@link CompositeDataMovementEvent}
@@ -275,7 +275,7 @@ public abstract int routeInputErrorEventToSource(int destinationTaskIndex,
* target input indices set to enable the routing. If the routing metadata is
* common across different events then the plugin can cache and reuse the same
* object.
- *
+ *
* @param sourceTaskIndex
* The index of the failed task in the source vertex of this edge.
* @param destinationTaskIndex
@@ -287,7 +287,7 @@ public abstract int routeInputErrorEventToSource(int destinationTaskIndex,
*/
public abstract @Nullable EventRouteMetadata routeInputSourceTaskFailedEventToDestination(
int sourceTaskIndex, int destinationTaskIndex) throws Exception;
-
+
/**
* Return the {@link org.apache.tez.dag.api.EdgeManagerPluginContext} for this specific instance of
* the vertex manager.
@@ -305,7 +305,7 @@ public EdgeManagerPluginContext getContext() {
* The event will be routed to every destination task index in the key of the
* map. Every physical input in the value for that task key will receive the
* input.
- *
+ *
* @param event
* Data movement event that contains the output information
* @param sourceTaskIndex
@@ -329,7 +329,7 @@ public void routeDataMovementEventToDestination(DataMovementEvent event,
* for that task key will receive the failure notification. This method will
* be called once for every source task failure and information for all
* affected destinations must be provided in that invocation.
- *
+ *
* @param sourceTaskIndex
* Source task
* @param destinationTaskAndInputIndices
@@ -341,19 +341,19 @@ public void routeInputSourceTaskFailedEventToDestination(int sourceTaskIndex,
/**
* Return the source task index to which to send the input error event
- *
+ *
* @param event
* Input read error event. Has more information about the error
* @param destinationTaskIndex
* Destination task that reported the error
* @param destinationFailedInputIndex
- * Index of the physical input on the destination task that reported
+ * Index of the physical input on the destination task that reported
* the error
* @return Index of the source task that created the unavailable input
* @throws Exception
*/
public int routeInputErrorEventToSource(InputReadErrorEvent event,
- int destinationTaskIndex, int destinationFailedInputIndex) throws Exception {
+ int destinationTaskIndex, int destinationFailedInputIndex) throws Exception {
return routeInputErrorEventToSource(destinationTaskIndex, destinationFailedInputIndex);
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/EdgeProperty.java b/tez-api/src/main/java/org/apache/tez/dag/api/EdgeProperty.java
index 07fb2c140f..1850060ece 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/EdgeProperty.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/EdgeProperty.java
@@ -21,7 +21,7 @@
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
/**
* An @link {@link EdgeProperty} defines the relation between the source and
@@ -43,7 +43,7 @@ public class EdgeProperty {
*/
public enum DataMovementType {
/**
- * Output on this edge produced by the i-th source task is available to the
+ * Output on this edge produced by the i-th source task is available to the
* i-th destination task.
*/
ONE_TO_ONE,
@@ -58,20 +58,20 @@ public enum DataMovementType {
* are gathered by designated destination tasks.
*/
SCATTER_GATHER,
-
+
/**
* Custom routing defined by the user.
*/
CUSTOM
}
-
+
/**
* Determines the lifetime of the data produced on this edge by a source task.
*/
public enum DataSourceType {
/**
* Data produced by the source is persisted and available even when the
- * task is not running. The data may become unavailable and may cause the
+ * task is not running. The data may become unavailable and may cause the
* source task to be re-executed.
*/
PERSISTED,
@@ -82,31 +82,51 @@ public enum DataSourceType {
PERSISTED_RELIABLE,
/**
* Data produced by the source task is available only while the source task
- * is running. This requires the destination task to run concurrently with
- * the source task. This is not supported yet.
+ * is running. This requires the destination task to run concurrently with
+ * the source task. Development in progress.
*/
@Unstable
EPHEMERAL
}
-
+
/**
- * Determines when the destination task is eligible to run, once the source
+ * Determines when the destination task is eligible to run, once the source
* task is eligible to run.
*/
public enum SchedulingType {
/**
- * Destination task is eligible to run after one or more of its source tasks
+ * Destination task is eligible to run after one or more of its source tasks
* have started or completed.
*/
SEQUENTIAL,
/**
* Destination task must run concurrently with the source task.
- * This is not supported yet.
+ * Development in progress.
*/
@Unstable
CONCURRENT
}
-
+
+ /**
+ * Determines the relevant event(s) that will assist in scheduling downstream vertex
+ * connected via a edge with CONCURRENT {@link SchedulingType}.
+ */
+ public enum ConcurrentEdgeTriggerType {
+ /**
+ * trigger tasks scheduling for downstream vertex(es) upon upstream being configured
+ * this effectively simultaneously schedules downstream and upstream vertices
+ * connected on both ends of a concurrent edge.
+ */
+ SOURCE_VERTEX_CONFIGURED,
+
+ /**
+ * trigger tasks scheduling for downstream vertex(es) by "running" event(s) of upstream tasks
+ * this will be fully supported with TEZ-3999
+ */
+ SOURCE_TASK_STARTED
+ }
+
+
final DataMovementType dataMovementType;
final DataSourceType dataSourceType;
final SchedulingType schedulingType;
@@ -172,7 +192,7 @@ private EdgeProperty(DataMovementType dataMovementType,
Preconditions.checkArgument(dataMovementType != DataMovementType.CUSTOM,
DataMovementType.CUSTOM + " cannot be used with this constructor");
}
-
+
private EdgeProperty(EdgeManagerPluginDescriptor edgeManagerDescriptor,
DataSourceType dataSourceType,
@@ -182,7 +202,7 @@ private EdgeProperty(EdgeManagerPluginDescriptor edgeManagerDescriptor,
this(edgeManagerDescriptor, DataMovementType.CUSTOM, dataSourceType, schedulingType,
edgeSource, edgeDestination);
}
-
+
private EdgeProperty(EdgeManagerPluginDescriptor edgeManagerDescriptor,
DataMovementType dataMovementType, DataSourceType dataSourceType,
SchedulingType schedulingType, OutputDescriptor edgeSource, InputDescriptor edgeDestination) {
@@ -193,7 +213,7 @@ private EdgeProperty(EdgeManagerPluginDescriptor edgeManagerDescriptor,
this.inputDescriptor = edgeDestination;
this.outputDescriptor = edgeSource;
}
-
+
/**
* Get the {@link DataMovementType}
* @return {@link DataMovementType}
@@ -201,7 +221,7 @@ private EdgeProperty(EdgeManagerPluginDescriptor edgeManagerDescriptor,
public DataMovementType getDataMovementType() {
return dataMovementType;
}
-
+
/**
* Get the {@link DataSourceType}
* @return {@link DataSourceType}
@@ -209,7 +229,7 @@ public DataMovementType getDataMovementType() {
public DataSourceType getDataSourceType() {
return dataSourceType;
}
-
+
/**
* Get the {@link SchedulingType}
* @return {@link SchedulingType}
@@ -217,30 +237,30 @@ public DataSourceType getDataSourceType() {
public SchedulingType getSchedulingType() {
return schedulingType;
}
-
+
/**
* @return the {@link InputDescriptor} which will consume data from the edge.
*/
public InputDescriptor getEdgeDestination() {
return inputDescriptor;
}
-
+
/**
* @return the {@link OutputDescriptor} which produces data on the edge.
*/
public OutputDescriptor getEdgeSource() {
return outputDescriptor;
}
-
+
/**
- * Returns the Edge Manager specifications for this edge.
+ * Returns the Edge Manager specifications for this edge.
* @return @link {@link EdgeManagerPluginDescriptor} if a custom edge was setup, null otherwise.
*/
@Private
public EdgeManagerPluginDescriptor getEdgeManagerDescriptor() {
return edgeManagerDescriptor;
}
-
+
@Override
public String toString() {
return "{ " + dataMovementType + " : " + inputDescriptor.getClassName()
@@ -248,5 +268,5 @@ public String toString() {
+ " >> " + (edgeManagerDescriptor == null ? "NullEdgeManager" : edgeManagerDescriptor.getClassName())
+ " }";
}
-
+
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/EntityDescriptor.java b/tez-api/src/main/java/org/apache/tez/dag/api/EntityDescriptor.java
index dcc4ebf779..2c7b834c1c 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/EntityDescriptor.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/EntityDescriptor.java
@@ -22,15 +22,15 @@
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Objects;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.io.DataOutputBuffer;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
-import com.google.common.base.Preconditions;
-
/**
* Describes a given user code entity. Consists of the name of the class implementing
* the user logic and a payload that can be used to configure an object instance of
@@ -65,7 +65,7 @@ public UserPayload getUserPayload() {
* @return this object for further chained method calls
*/
public T setUserPayload(UserPayload userPayload) {
- Preconditions.checkNotNull(userPayload);
+ Objects.requireNonNull(userPayload);
this.userPayload = userPayload;
return (T) this;
}
@@ -94,36 +94,40 @@ public String getClassName() {
return this.className;
}
+ void writeSingular(DataOutput out, ByteBuffer bb) throws IOException {
+ out.write(bb.array(), 0, bb.array().length);
+ }
+
+ void writeSegmented(DataOutput out, ByteBuffer bb) throws IOException {
+ // This code is just for fallback in case serialization is changed to
+ // use something other than DataOutputBuffer.
+ int len;
+ byte[] buf = new byte[SERIALIZE_BUFFER_SIZE];
+ do {
+ len = Math.min(bb.remaining(), SERIALIZE_BUFFER_SIZE);
+ bb.get(buf, 0, len);
+ out.write(buf, 0, len);
+ } while (bb.remaining() > 0);
+ }
+
@Override
public void write(DataOutput out) throws IOException {
Text.writeString(out, className);
// TODO: TEZ-305 - using protobuf serde instead of Writable serde.
ByteBuffer bb = DagTypeConverters.convertFromTezUserPayload(userPayload);
- if (bb == null) {
+ if (bb == null || bb.remaining() == 0) {
out.writeInt(-1);
+ return;
+ }
+
+ // write size
+ out.writeInt(bb.remaining());
+ if (bb.hasArray()) {
+ writeSingular(out, bb);
} else {
- int size = bb.remaining();
- if (size == 0) {
- out.writeInt(-1);
- } else {
- out.writeInt(size);
- if (out instanceof DataOutputBuffer) {
- DataOutputBuffer buf = (DataOutputBuffer) out;
- buf.write(new ByteBufferDataInput(bb), size);
- } else {
- // This code is just for fallback in case serialization is changed to
- // use something other than DataOutputBuffer.
- int len;
- byte[] buf = new byte[SERIALIZE_BUFFER_SIZE];
- do {
- len = Math.min(bb.remaining(), SERIALIZE_BUFFER_SIZE);
- bb.get(buf, 0, len);
- out.write(buf, 0, len);
- } while (bb.remaining() > 0);
- }
- }
- out.writeInt(userPayload.getVersion());
+ writeSegmented(out, bb);
}
+ out.writeInt(userPayload.getVersion());
}
@Override
@@ -144,76 +148,4 @@ public String toString() {
userPayload == null ? false : userPayload.getPayload() == null ? false : true;
return "ClassName=" + className + ", hasPayload=" + hasPayload;
}
-
- private static class ByteBufferDataInput implements DataInput {
-
- private final ByteBuffer bb;
-
- public ByteBufferDataInput(ByteBuffer bb) {
- this.bb = bb;
- }
-
- @Override
- public void readFully(byte[] b) throws IOException {
- bb.get(b, 0, bb.remaining());
- }
-
- @Override
- public void readFully(byte[] b, int off, int len) throws IOException {
- bb.get(b, off, len);
- }
-
- @Override
- public int skipBytes(int n) throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public boolean readBoolean() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public byte readByte() throws IOException {
- return bb.get();
- }
- @Override
- public int readUnsignedByte() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public short readShort() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public int readUnsignedShort() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public char readChar() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public int readInt() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public long readLong() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public float readFloat() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public double readDouble() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public String readLine() throws IOException {
- throw new UnsupportedOperationException();
- }
- @Override
- public String readUTF() throws IOException {
- throw new UnsupportedOperationException();
- }
- }
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/NamedEntityDescriptor.java b/tez-api/src/main/java/org/apache/tez/dag/api/NamedEntityDescriptor.java
index 426d4eb1b0..86ae26c876 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/NamedEntityDescriptor.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/NamedEntityDescriptor.java
@@ -17,8 +17,8 @@
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
+import java.util.Objects;
-import com.google.common.base.Preconditions;
import org.apache.hadoop.classification.InterfaceAudience;
@SuppressWarnings("unchecked")
@@ -28,8 +28,7 @@ public class NamedEntityDescriptor> extends E
@InterfaceAudience.Private
public NamedEntityDescriptor(String entityName, String className) {
super(className);
- Preconditions.checkArgument(entityName != null, "EntityName must be specified");
- this.entityName = entityName;
+ this.entityName = Objects.requireNonNull(entityName, "EntityName must be specified");
}
public String getEntityName() {
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/NoCurrentDAGException.java b/tez-api/src/main/java/org/apache/tez/dag/api/NoCurrentDAGException.java
new file mode 100644
index 0000000000..26ef89abab
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/NoCurrentDAGException.java
@@ -0,0 +1,39 @@
+/**
+* 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.tez.dag.api;
+
+import org.apache.hadoop.classification.InterfaceAudience.Private;
+
+/**
+ * Fatal exception: thrown by the AM if there is no DAG running when
+ * a DAG's status is queried. This is different from {@link org.apache.tez.dag.api.DAGNotRunningException}
+ * in a sense that this exception is fatal, in which scenario the client might consider the DAG failed, because
+ * it tries to ask a status from an AM which is not currently running a DAG. This scenario is possible in case
+ * an AM is restarted and the DagClient fails to realize it's asking the status of a possibly lost DAG.
+ */
+@Private
+public class NoCurrentDAGException extends TezException {
+ private static final long serialVersionUID = 6337442733802964448L;
+
+ public static final String MESSAGE_PREFIX = "No running DAG at present";
+
+ public NoCurrentDAGException(String dagId) {
+ super(MESSAGE_PREFIX + ": " + dagId);
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/TaskLocationHint.java b/tez-api/src/main/java/org/apache/tez/dag/api/TaskLocationHint.java
index d1a1359977..3070c338cc 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/TaskLocationHint.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/TaskLocationHint.java
@@ -20,12 +20,13 @@
import java.util.Collections;
import java.util.Set;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Evolving;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
/**
* Describes the placements hints for tasks.
@@ -67,7 +68,7 @@ public String toString() {
private TaskBasedLocationAffinity affinitizedTask;
private TaskLocationHint(String vertexName, int taskIndex) {
- Preconditions.checkNotNull(vertexName);
+ Objects.requireNonNull(vertexName);
Preconditions.checkArgument(taskIndex >= 0);
this.affinitizedTask = new TaskBasedLocationAffinity(vertexName, taskIndex);
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java b/tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java
index 39688d68bc..8862f4b7d6 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/TezConfiguration.java
@@ -26,22 +26,25 @@
import java.util.Map;
import java.util.Set;
-import org.apache.tez.common.annotation.ConfigurationClass;
-import org.apache.tez.common.annotation.ConfigurationProperty;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.concurrent.TimeUnit;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.Shell;
import org.apache.hadoop.yarn.api.records.LocalResource;
+import org.apache.tez.common.TezCommonUtils;
+import org.apache.tez.common.annotation.ConfigurationClass;
+import org.apache.tez.common.annotation.ConfigurationProperty;
+import org.apache.tez.dag.api.EdgeProperty.ConcurrentEdgeTriggerType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
/**
- * Defines the configurations for Tez. These configurations are typically specified in
+ * Defines the configurations for Tez. These configurations are typically specified in
* tez-site.xml on the client machine where TezClient is used to launch the Tez application.
* tez-site.xml is expected to be picked up from the classpath of the client process.
* @see Detailed Configuration Information
@@ -55,7 +58,7 @@ public class TezConfiguration extends Configuration {
private final static Logger LOG = LoggerFactory.getLogger(TezConfiguration.class);
- private static Map PropertyScope = new HashMap();
+ private static Map PropertyScope = new HashMap<>();
static {
Configuration.addDeprecation("tez.am.counters.max.keys", TezConfiguration.TEZ_COUNTERS_MAX);
@@ -131,7 +134,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_TASK_PREFIX = TEZ_PREFIX + "task.";
/**
- * Boolean value. If true then Tez will try to automatically delete temporary job
+ * Boolean value. If true then Tez will try to automatically delete temporary job
* artifacts that it creates within the specified staging dir. Does not affect any user data.
*/
@ConfigurationScope(Scope.AM)
@@ -183,7 +186,7 @@ public TezConfiguration(boolean loadDefaults) {
+ "use.concurrent-dispatcher";
@Private
public static boolean TEZ_AM_USE_CONCURRENT_DISPATCHER_DEFAULT = false;
-
+
@Private
@ConfigurationScope(Scope.AM)
public static final String TEZ_AM_CONCURRENT_DISPATCHER_CONCURRENCY = TEZ_AM_PREFIX
@@ -191,12 +194,23 @@ public TezConfiguration(boolean loadDefaults) {
@Private
public static final int TEZ_AM_CONCURRENT_DISPATCHER_CONCURRENCY_DEFAULT = 10;
+ /**
+ * Integer value. Milliseconds while AsyncDispatcher should wait for events to be processed on
+ * serviceStop. The idea is borrowed from YARN-3999.
+ */
+ @Private
+ @ConfigurationScope(Scope.AM)
+ public static final String TEZ_AM_DISPATCHER_DRAIN_EVENTS_TIMEOUT = TEZ_AM_PREFIX
+ + "dispatcher.drain-events.timeout";
+ @Private
+ public static final int TEZ_AM_DISPATCHER_DRAIN_EVENTS_TIMEOUT_DEFAULT = 10000;
+
/**
* Boolean value. Execution mode for the Tez application. True implies session mode. If the client
* code is written according to best practices then the same code can execute in either mode based
* on this configuration. Session mode is more aggressive in reserving execution resources and is
* typically used for interactive applications where multiple DAGs are submitted in quick succession
- * by the same user. For long running applications, one-off executions, batch jobs etc non-session
+ * by the same user. For long running applications, one-off executions, batch jobs etc non-session
* mode is recommended. If session mode is enabled then container reuse is recommended.
*/
@ConfigurationScope(Scope.AM)
@@ -246,6 +260,51 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_TASK_LOG_LEVEL = TEZ_TASK_PREFIX + "log.level";
public static final String TEZ_TASK_LOG_LEVEL_DEFAULT = "INFO";
+ /**
+ * By this option, user can easily override the logging pattern which is applied in
+ * TezContainerLogAppender in AM, regardless of the environmental settings.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_LOG_PATTERN_LAYOUT_AM = TEZ_AM_PREFIX + "log.pattern.layout";
+
+ /**
+ * By this option, user can easily override the logging pattern which is applied in
+ * TezContainerLogAppender in tasks, regardless of the environmental settings.
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_LOG_PATTERN_LAYOUT_TASK = TEZ_TASK_PREFIX + "log.pattern.layout";
+
+ /**
+ * Set pattern to empty string to turn the custom log pattern feature off.
+ */
+ public static final String TEZ_LOG_PATTERN_LAYOUT_DEFAULT = "";
+
+ /**
+ * Comma separated list of keys, which can used for defining keys in MDC. The corresponding values
+ * will be read from Configuration, see tez.mdc.custom.keys.conf.props for further details.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_MDC_CUSTOM_KEYS = TEZ_PREFIX + "mdc.custom.keys";
+
+ /**
+ * Comma separated list of Configuration keys. Tez will try to fill MDC with key value pairs in a
+ * way that a key will be the nth item in tez.mdc.custom.keys and the value will be the value from
+ * a Configuration object pointed by the nth key of tez.mdc.custom.keys.conf.props like below:
+ *
+ * tez.mdc.custom.keys=queryId,otherKey
+ * tez.mdc.custom.keys.conf.props=awesome.sql.app.query.id,awesome.sql.app.other.key
+ *
+ * So MDC will contain key -{@literal >} value pairs as:
+ * queryId -{@literal >} conf.get("awesome.sql.app.query.id")
+ * otherKey -{@literal >} conf.get("awesome.sql.app.other.key")
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_MDC_CUSTOM_KEYS_CONF_PROPS = TEZ_MDC_CUSTOM_KEYS + ".conf.props";
+
/**
* double value. Represents ratio of unique failed outputs / number of consumer
* tasks. When this condition or value mentioned in {@link
@@ -271,12 +330,12 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_TASK_MAX_ALLOWED_OUTPUT_FAILURES_DEFAULT = 10;
/**
- * int value. Represents the maximum time in seconds for which a consumer attempt can report
- * a read error against its producer attempt, after which the producer attempt will be re-run
- * to re-generate the output. There are other heuristics which determine the retry and mainly
- * try to guard against a flurry of re-runs due to intermittent read errors
+ * int value. Represents the maximum time in seconds for which a consumer attempt can report
+ * a read error against its producer attempt, after which the producer attempt will be re-run
+ * to re-generate the output. There are other heuristics which determine the retry and mainly
+ * try to guard against a flurry of re-runs due to intermittent read errors
* (due to network issues). This configuration puts a time limit on those heuristics to ensure
- * jobs dont hang indefinitely due to lack of closure in those heuristics
+ * jobs dont hang indefinitely due to lack of closure in those heuristics
*
* Expert level setting.
*/
@@ -286,11 +345,29 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_AM_PREFIX + "max.allowed.time-sec.for-read-error";
public static final int TEZ_AM_MAX_ALLOWED_TIME_FOR_TASK_READ_ERROR_SEC_DEFAULT = 300;
+ /**
+ * Double value. Assuming that a certain number of downstream hosts reported fetch failure for a
+ * given upstream host, this config drives the max allowed ratio of (downstream hosts) / (all hosts).
+ * The total number of used hosts are tracked by AMNodeTracker, which divides the distinct number of
+ * downstream hosts blaming source(upstream) tasks in a given vertex. If the fraction is beyond this
+ * limit, the upstream task attempt is marked as failed (so blamed for the fetch failure).
+ * E.g. if this set to 0.2, in case of 3 different hosts reporting fetch failure
+ * for the same upstream host in a cluster which currently utilizes 10 nodes, the upstream task
+ * is immediately blamed for the fetch failure.
+ *
+ * Expert level setting.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_AM_MAX_ALLOWED_DOWNSTREAM_HOST_FAILURES_FRACTION =
+ TEZ_AM_PREFIX + "max.allowed.downstream.host.failures.fraction";
+ public static final double TEZ_AM_MAX_ALLOWED_DOWNSTREAM_HOST_FAILURES_FRACTION_DEFAULT = 0.2;
+
/**
* Boolean value. Determines when the final outputs to data sinks are committed. Commit is an
- * output specific operation and typically involves making the output visible for consumption.
- * If the config is true, then the outputs are committed at the end of DAG completion after all
- * constituent vertices have completed. If false, outputs for each vertex are committed after that
+ * output specific operation and typically involves making the output visible for consumption.
+ * If the config is true, then the outputs are committed at the end of DAG completion after all
+ * constituent vertices have completed. If false, outputs for each vertex are committed after that
* vertex succeeds. Depending on the desired output visibility and downstream consumer dependencies
* this value must be appropriately chosen. Defaults to the safe choice of true.
*/
@@ -330,8 +407,11 @@ public TezConfiguration(boolean loadDefaults) {
@ConfigurationScope(Scope.AM)
@ConfigurationProperty
public static final String TEZ_AM_LAUNCH_CMD_OPTS = TEZ_AM_PREFIX + "launch.cmd-opts";
- public static final String TEZ_AM_LAUNCH_CMD_OPTS_DEFAULT =
+ public static final String TEZ_AM_LAUNCH_CMD_OPTS_JDK8_DEFAULT =
"-XX:+PrintGCDetails -verbose:gc -XX:+PrintGCTimeStamps -XX:+UseNUMA -XX:+UseParallelGC";
+ public static final String TEZ_AM_LAUNCH_CMD_OPTS_JDK9_DEFAULT =
+ "-verbose:gc -Xlog:gc*,safepoint::time,uptime -XX:+UseNUMA -XX:+UseParallelGC";
+ public static final String TEZ_AM_LAUNCH_CMD_OPTS_DEFAULT;
/**
* String value. Command line options which will be prepended to {@link
@@ -355,8 +435,21 @@ public TezConfiguration(boolean loadDefaults) {
@ConfigurationProperty
public static final String TEZ_TASK_LAUNCH_CMD_OPTS = TEZ_TASK_PREFIX
+ "launch.cmd-opts";
- public static final String TEZ_TASK_LAUNCH_CMD_OPTS_DEFAULT =
+ public static final String TEZ_TASK_LAUNCH_CMD_OPTS_JDK8_DEFAULT =
"-XX:+PrintGCDetails -verbose:gc -XX:+PrintGCTimeStamps -XX:+UseNUMA -XX:+UseParallelGC";
+ public static final String TEZ_TASK_LAUNCH_CMD_OPTS_JDK9_DEFAULT =
+ "-verbose:gc -Xlog:gc*,safepoint::time,uptime -XX:+UseNUMA -XX:+UseParallelGC";
+ public static final String TEZ_TASK_LAUNCH_CMD_OPTS_DEFAULT;
+
+ static {
+ if (TezCommonUtils.getJavaVersion() >= 9) {
+ TEZ_AM_LAUNCH_CMD_OPTS_DEFAULT = TEZ_AM_LAUNCH_CMD_OPTS_JDK9_DEFAULT;
+ TEZ_TASK_LAUNCH_CMD_OPTS_DEFAULT = TEZ_TASK_LAUNCH_CMD_OPTS_JDK9_DEFAULT;
+ } else {
+ TEZ_AM_LAUNCH_CMD_OPTS_DEFAULT = TEZ_AM_LAUNCH_CMD_OPTS_JDK8_DEFAULT;
+ TEZ_TASK_LAUNCH_CMD_OPTS_DEFAULT = TEZ_TASK_LAUNCH_CMD_OPTS_JDK8_DEFAULT;
+ }
+ }
/**
* Double value. Tez automatically determines the Xmx for the JVMs used to run
@@ -408,6 +501,19 @@ public TezConfiguration(boolean loadDefaults) {
+ "launch.env";
public static final String TEZ_AM_LAUNCH_ENV_DEFAULT = "";
+ /**
+ * String value. In the presence of concurrent input edge to a vertex, this describes
+ * the timing of scheduling downstream vertex tasks. It may be closely related to the
+ * type of event that will contribute to a scheduling decision.
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_CONCURRENT_EDGE_TRIGGER_TYPE =
+ TEZ_TASK_PREFIX + "concurrent.edge.trigger.type";
+ public static final String TEZ_CONCURRENT_EDGE_TRIGGER_TYPE_DEFAULT =
+ ConcurrentEdgeTriggerType.SOURCE_VERTEX_CONFIGURED.name();
+
+
/**
* String value. Env settings will be merged with {@link #TEZ_TASK_LAUNCH_ENV}
* during the launch of the task process. This property will typically be configured to
@@ -508,16 +614,16 @@ public TezConfiguration(boolean loadDefaults) {
@Unstable
/**
- * Boolean value. Enable speculative execution of slower tasks. This can help reduce job latency
+ * Boolean value. Enable speculative execution of slower tasks. This can help reduce job latency
* when some tasks are running slower due bad/slow machines
*/
@ConfigurationScope(Scope.VERTEX) // TODO Verify the vertex speculation, TEZ-1788
@ConfigurationProperty(type="boolean")
public static final String TEZ_AM_SPECULATION_ENABLED = TEZ_AM_PREFIX + "speculation.enabled";
public static final boolean TEZ_AM_SPECULATION_ENABLED_DEFAULT = false;
-
+
/**
- * Float value. Specifies how many standard deviations away from the mean task execution time
+ * Float value. Specifies how many standard deviations away from the mean task execution time
* should be considered as an outlier/slow task.
*/
@Unstable
@@ -526,16 +632,129 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_AM_LEGACY_SPECULATIVE_SLOWTASK_THRESHOLD =
TEZ_AM_PREFIX + "legacy.speculative.slowtask.threshold";
+ /**
+ * Long value. Specifies the timeout after which tasks on a single task vertex must be speculated.
+ * A negative value means not to use timeout for speculation of single task vertices.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_AM_LEGACY_SPECULATIVE_SINGLE_TASK_VERTEX_TIMEOUT =
+ TEZ_AM_PREFIX + "legacy.speculative.single.task.vertex.timeout";
+ public static final long TEZ_AM_LEGACY_SPECULATIVE_SINGLE_TASK_VERTEX_TIMEOUT_DEFAULT = -1;
+
+ @Private
+ public static final String TEZ_SPECULATOR_PREFIX = TEZ_AM_PREFIX + "speculator.";
+ @Private
+ public static final String TEZ_ESTIMATOR_PREFIX = TEZ_AM_PREFIX + "task.estimator.";
+ /**
+ * Long value. Specifies amount of time (in ms) that needs to elapse to do the next round of
+ * speculation if there is no task speculated in this round.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_AM_SOONEST_RETRY_AFTER_NO_SPECULATE =
+ TEZ_AM_PREFIX + "soonest.retry.after.no.speculate";
+ public static final long TEZ_AM_SOONEST_RETRY_AFTER_NO_SPECULATE_DEFAULT = 1000L * 1L;
+
+ /**
+ * Long value. Specifies amount of time (in ms) that needs to elapse to do the next round of
+ * speculation if there are tasks speculated in this round.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_AM_SOONEST_RETRY_AFTER_SPECULATE=
+ TEZ_AM_PREFIX + "soonest.retry.after.speculate";
+ public static final long TEZ_AM_SOONEST_RETRY_AFTER_SPECULATE_DEFAULT = 1000L * 15L;
+
+ /** The class that should be used for speculative execution calculations. */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_AM_SPECULATOR_CLASS =
+ TEZ_SPECULATOR_PREFIX + "class";
+ /** The class that should be used for task runtime estimation. */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_AM_TASK_ESTIMATOR_CLASS =
+ TEZ_ESTIMATOR_PREFIX + "class";
+ /**
+ * Long value. Specifies amount of time (in ms) of the lambda value in the
+ * smoothing function of the task estimator
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_AM_ESTIMATOR_EXPONENTIAL_LAMBDA_MS =
+ TEZ_ESTIMATOR_PREFIX + "exponential.lambda.ms";
+ public static final long TEZ_AM_ESTIMATOR_EXPONENTIAL_LAMBDA_MS_DEFAULT =
+ TimeUnit.SECONDS.toMillis(120);
+
+ /**
+ * The window length in the simple exponential smoothing that considers the
+ * task attempt is stagnated.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_AM_ESTIMATOR_EXPONENTIAL_STAGNATED_MS =
+ TEZ_ESTIMATOR_PREFIX + "exponential.stagnated.ms";
+ public static final long TEZ_AM_ESTIMATOR_EXPONENTIAL_STAGNATED_MS_DEFAULT =
+ TimeUnit.SECONDS.toMillis(360);
+
+ /**
+ * The number of initial readings that the estimator ignores before giving a
+ * prediction. At the beginning the smooth estimator won't be accurate in
+ * prediction
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_AM_ESTIMATOR_EXPONENTIAL_SKIP_INITIALS =
+ TEZ_ESTIMATOR_PREFIX + "exponential.skip.initials";
+ public static final int TEZ_AM_ESTIMATOR_EXPONENTIAL_SKIP_INITIALS_DEFAULT = 24;
+
+ /**
+ * Double value. The max percent (0-1) of running tasks that can be speculatively re-executed at any time.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="double")
+ public static final String TEZ_AM_PROPORTION_RUNNING_TASKS_SPECULATABLE =
+ TEZ_AM_PREFIX + "proportion.running.tasks.speculatable";
+ public static final double TEZ_AM_PROPORTION_RUNNING_TASKS_SPECULATABLE_DEFAULT = 0.1;
+
+ /**
+ * Double value. The max percent (0-1) of all tasks that can be speculatively re-executed at any time.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="double")
+ public static final String TEZ_AM_PROPORTION_TOTAL_TASKS_SPECULATABLE =
+ TEZ_AM_PREFIX + "proportion.total.tasks.speculatable";
+ public static final double TEZ_AM_PROPORTION_TOTAL_TASKS_SPECULATABLE_DEFAULT = 0.01;
+
+ /**
+ * Integer value. The minimum allowed tasks that can be speculatively re-executed at any time.
+ */
+ @Unstable
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_AM_MINIMUM_ALLOWED_SPECULATIVE_TASKS =
+ TEZ_AM_PREFIX + "minimum.allowed.speculative.tasks";
+ public static final int TEZ_AM_MINIMUM_ALLOWED_SPECULATIVE_TASKS_DEFAULT = 10;
+
/**
* Int value. Upper limit on the number of threads user to launch containers in the app
- * master. Expert level setting.
+ * master. Expert level setting.
*/
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
public static final String TEZ_AM_CONTAINERLAUNCHER_THREAD_COUNT_LIMIT =
TEZ_AM_PREFIX + "containerlauncher.thread-count-limit";
- public static final int TEZ_AM_CONTAINERLAUNCHER_THREAD_COUNT_LIMIT_DEFAULT =
+ public static final int TEZ_AM_CONTAINERLAUNCHER_THREAD_COUNT_LIMIT_DEFAULT =
500;
@@ -549,8 +768,8 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_AM_MAX_TASK_FAILURES_PER_NODE_DEFAULT = 10;
/**
- * Int value. Specifies the number of times the app master can be launched in order to recover
- * from app master failure. Typically app master failures are non-recoverable. This parameter
+ * Int value. Specifies the number of times the app master can be launched in order to recover
+ * from app master failure. Typically app master failures are non-recoverable. This parameter
* is for cases where the app master is not at fault but is lost due to system errors.
* Expert level setting.
*/
@@ -571,7 +790,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_AM_VERTEX_MAX_TASK_CONCURRENCY_DEFAULT = -1;
/**
- * Int value. The maximum number of attempts that can fail for a particular task before the task is failed.
+ * Int value. The maximum number of attempts that can fail for a particular task before the task is failed.
* This does not count killed attempts. Task failure results in DAG failure.
*/
@ConfigurationScope(Scope.VERTEX)
@@ -580,9 +799,19 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_AM_PREFIX + "task.max.failed.attempts";
public static final int TEZ_AM_TASK_MAX_FAILED_ATTEMPTS_DEFAULT = 4;
+ /**
+ * Int value. The maximum number of attempts that can run for a particular task before the task is
+ * failed. This count every attempts, including failed, killed attempts. Task failure results in
+ * DAG failure. Default is 0, which disables this feature.
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type = "integer")
+ public static final String TEZ_AM_TASK_MAX_ATTEMPTS = TEZ_AM_PREFIX + "task.max.attempts";
+ public static final int TEZ_AM_TASK_MAX_ATTEMPTS_DEFAULT = 0;
+
/**
* Boolean value. Specifies whether a re-scheduled attempt of a task, caused by previous
- * failures gets special treatment - higher priority, dropped location hints.
+ * failures gets higher priority
*/
@ConfigurationScope(Scope.VERTEX)
@ConfigurationProperty(type="boolean")
@@ -591,7 +820,17 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean TEZ_AM_TASK_RESCHEDULE_HIGHER_PRIORITY_DEFAULT=true;
/**
- * Boolean value. Enabled blacklisting of nodes of nodes that are considered faulty. These nodes
+ * Boolean value. Specifies whether a re-scheduled attempt of a task, caused by previous
+ * failure get relaxed locality
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_AM_TASK_RESCHEDULE_RELAXED_LOCALITY =
+ TEZ_AM_PREFIX + "task.reschedule.relaxed.locality";
+ public static final boolean TEZ_AM_TASK_RESCHEDULE_RELAXED_LOCALITY_DEFAULT=true;
+
+ /**
+ * Boolean value. Enabled blacklisting of nodes of nodes that are considered faulty. These nodes
* will not be used to execute tasks.
*/
@ConfigurationScope(Scope.AM)
@@ -599,11 +838,11 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_AM_NODE_BLACKLISTING_ENABLED = TEZ_AM_PREFIX
+ "node-blacklisting.enabled";
public static final boolean TEZ_AM_NODE_BLACKLISTING_ENABLED_DEFAULT = true;
-
+
/**
* Int value. Specifies the percentage of nodes in the cluster that may be considered faulty.
- * This limits the number of nodes that are blacklisted in an effort to minimize the effects of
- * temporary surges in failures (e.g. due to network outages).
+ * This limits the number of nodes that are blacklisted in an effort to minimize the effects of
+ * temporary surges in failures (e.g. due to network outages).
*/
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
@@ -630,7 +869,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_AM_CLIENT_THREAD_COUNT =
TEZ_AM_PREFIX + "client.am.thread-count";
public static final int TEZ_AM_CLIENT_THREAD_COUNT_DEFAULT = 2;
-
+
/**
* String value. Range of ports that the AM can use when binding for client connections. Leave blank
* to use all possible ports. Expert level setting. It's hadoop standard range configuration.
@@ -659,6 +898,26 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_AM_DAG_SCHEDULER_CLASS_DEFAULT =
"org.apache.tez.dag.app.dag.impl.DAGSchedulerNaturalOrder";
+ /**
+ * String value. The class to be used for the YARN task scheduler. Expert level setting.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_AM_YARN_SCHEDULER_CLASS = TEZ_AM_PREFIX + "yarn.scheduler.class";
+ public static final String TEZ_AM_YARN_SCHEDULER_CLASS_DEFAULT =
+ "org.apache.tez.dag.app.rm.DagAwareYarnTaskScheduler";
+
+ /**
+ * Int value. The AM waits this amount of time when the first DAG is submitted but not all the services are ready.
+ * This can happen when the client RPC handler is up and able to accept DAGs but e.g. task scheduler
+ * manager is not ready (e.g. a task scheduler is waiting for external resources).
+ * A value equal or less than 0 is not supported and leads to an exception.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_AM_READY_FOR_SUBMIT_TIMEOUT_MS = TEZ_AM_PREFIX + "ready.for.submit.timeout.ms";
+ public static final int TEZ_AM_READY_FOR_SUBMIT_TIMEOUT_MS_DEFAULT = 30000;
+
/** Int value. The amount of memory in MB to be used by the AppMaster */
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
@@ -681,7 +940,33 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean TEZ_AM_DAG_CLEANUP_ON_COMPLETION_DEFAULT = false;
/**
- * Int value. Upper limit on the number of threads used to delete DAG directories on nodes.
+ * Integer value. Instructs AM to delete vertex shuffle data if a vertex and all its
+ * child vertices at a certain depth are completed. Value less than or equal to 0 indicates the feature
+ * is disabled.
+ * Let's say we have a dag Map1 - Reduce2 - Reduce3 - Reduce4.
+ * case:1 height = 1
+ * when Reduce 2 completes all the shuffle data of Map1 will be deleted and so on for other vertex.
+ * case: 2 height = 2
+ * when Reduce 3 completes all the shuffle data of Map1 will be deleted and so on for other vertex.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_AM_VERTEX_CLEANUP_HEIGHT = TEZ_AM_PREFIX
+ + "vertex.cleanup.height";
+ public static final int TEZ_AM_VERTEX_CLEANUP_HEIGHT_DEFAULT = 0;
+
+ /**
+ * Boolean value. Instructs AM to delete intermediate attempt data for failed task attempts.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_AM_TASK_ATTEMPT_CLEANUP_ON_FAILURE = TEZ_AM_PREFIX
+ + "task.attempt.cleanup.on.failure";
+ public static final boolean TEZ_AM_TASK_ATTEMPT_CLEANUP_ON_FAILURE_DEFAULT = false;
+
+ /**
+ * Int value. Upper limit on the number of threads used to delete DAG directories,
+ * Vertex directories and failed task attempts directories on nodes.
*/
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
@@ -690,8 +975,18 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_AM_DAG_CLEANUP_THREAD_COUNT_LIMIT_DEFAULT = 10;
+ /**
+ * Int value. Upper limit on the number of threads used by app context (vertex management and input init events).
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_AM_DAG_APPCONTEXT_THREAD_COUNT_LIMIT =
+ TEZ_AM_PREFIX + "dag.appcontext.thread-count-limit";
+
+ public static final int TEZ_AM_DAG_APPCONTEXT_THREAD_COUNT_LIMIT_DEFAULT = 10;
+
/** Int value. The amount of memory in MB to be used by tasks. This applies to all tasks across
- * all vertices. Setting it to the same value for all tasks is helpful for container reuse and
+ * all vertices. Setting it to the same value for all tasks is helpful for container reuse and
* thus good for performance typically. */
@ConfigurationScope(Scope.DAG) // TODO vertex level
@ConfigurationProperty(type="integer")
@@ -706,7 +1001,7 @@ public TezConfiguration(boolean loadDefaults) {
@ConfigurationProperty(type="integer")
public static final String TEZ_TASK_RESOURCE_CPU_VCORES = TEZ_TASK_PREFIX
+ "resource.cpu.vcores";
- public static final int TEZ_TASK_RESOURCE_CPU_VCORES_DEFAULT = 1;
+ public static final int TEZ_TASK_RESOURCE_CPU_VCORES_DEFAULT = 1;
/**
* Int value. The maximum heartbeat interval between the AM and RM in milliseconds
@@ -721,7 +1016,7 @@ public TezConfiguration(boolean loadDefaults) {
/**
* Int value. The maximum amount of time, in milliseconds, to wait before a task asks an
- * AM for another task. Increasing this can help improve app master scalability for a large
+ * AM for another task. Increasing this can help improve app master scalability for a large
* number of concurrent tasks. Expert level setting.
*/
@ConfigurationScope(Scope.AM)
@@ -731,7 +1026,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_TASK_GET_TASK_SLEEP_INTERVAL_MS_MAX_DEFAULT = 200;
/**
- * Int value. The maximum heartbeat interval, in milliseconds, between the app master and tasks.
+ * Int value. The maximum heartbeat interval, in milliseconds, between the app master and tasks.
* Increasing this can help improve app master scalability for a large number of concurrent tasks.
* Expert level setting.
*/
@@ -742,8 +1037,8 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_TASK_AM_HEARTBEAT_INTERVAL_MS_DEFAULT = 100;
/**
- * Int value. Interval, in milliseconds, after which counters are sent to AM in heartbeat from
- * tasks. This reduces the amount of network traffice between AM and tasks to send high-volume
+ * Int value. Interval, in milliseconds, after which counters are sent to AM in heartbeat from
+ * tasks. This reduces the amount of network traffice between AM and tasks to send high-volume
* counters. Improves AM scalability. Expert level setting.
*/
@ConfigurationScope(Scope.AM)
@@ -762,7 +1057,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_TASK_MAX_EVENTS_PER_HEARTBEAT = TEZ_TASK_PREFIX
+ "max-events-per-heartbeat";
public static final int TEZ_TASK_MAX_EVENTS_PER_HEARTBEAT_DEFAULT = 500;
-
+
/**
* Int value. Maximum number of pending task events before a task will stop
* asking for more events in the task heartbeat.
@@ -797,16 +1092,16 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean TEZ_TASK_INITIALIZE_PROCESSOR_IO_SERIALLY_DEFAULT = false;
/**
- * Long value. Interval, in milliseconds, within which any of the tasks Input/Processor/Output
- * components need to make successive progress notifications. If the progress is not notified
+ * Long value. Interval, in milliseconds, within which any of the tasks Input/Processor/Output
+ * components need to make successive progress notifications. If the progress is not notified
* for this interval then the task will be considered hung and terminated.
- * The value for this config should be larger than {@link TezConfiguration#TASK_HEARTBEAT_TIMEOUT_MS}
+ * The value for this config should be larger than {@link TezConfiguration#TASK_HEARTBEAT_TIMEOUT_MS}
* and larger than 2 times the value of {@link TezConfiguration#TEZ_TASK_AM_HEARTBEAT_INTERVAL_MS}.
* A config value <=0 disables this.
*/
@ConfigurationScope(Scope.VERTEX)
@ConfigurationProperty
- public static final String TEZ_TASK_PROGRESS_STUCK_INTERVAL_MS = TEZ_TASK_PREFIX +
+ public static final String TEZ_TASK_PROGRESS_STUCK_INTERVAL_MS = TEZ_TASK_PREFIX +
"progress.stuck.interval-ms";
public static final long TEZ_TASK_PROGRESS_STUCK_INTERVAL_MS_DEFAULT = -1;
@@ -980,7 +1275,7 @@ public TezConfiguration(boolean loadDefaults) {
/**
* Boolean value. Whether to reuse containers for non-local tasks. Active only if reuse is
- * enabled. Turning this on can severely affect locality and can be bad for jobs with high data
+ * enabled. Turning this on can severely affect locality and can be bad for jobs with high data
* volume being read from the primary data sources.
*/
@ConfigurationScope(Scope.AM)
@@ -990,6 +1285,20 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean
TEZ_AM_CONTAINER_REUSE_NON_LOCAL_FALLBACK_ENABLED_DEFAULT = false;
+ /**
+ * Boolean value. Whether to reuse new containers that could not be immediately assigned to
+ * pending requests. If enabled then newly assigned containers that cannot be immediately
+ * allocated will be held for potential reuse as if it were a container that had just completed
+ * a task. If disabled then newly assigned containers that cannot be immediately allocated will
+ * be released. Active only if container reuse is enabled.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_AM_CONTAINER_REUSE_NEW_CONTAINERS_ENABLED =
+ TEZ_AM_PREFIX + "container.reuse.new-containers.enabled";
+ public static final boolean
+ TEZ_AM_CONTAINER_REUSE_NEW_CONTAINERS_ENABLED_DEFAULT = false;
+
/**
* Int value. The amount of time to wait before assigning a container to the next level
* of locality. NODE -> RACK -> NON_LOCAL. Delay scheduling parameter. Expert level setting.
@@ -1003,15 +1312,15 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_AM_CONTAINER_REUSE_LOCALITY_DELAY_ALLOCATION_MILLIS_DEFAULT = 250l;
/**
- * Int value. The minimum amount of time to hold on to a container that is idle. Only active when
- * reuse is enabled. Set to -1 to never release idle containers (not recommended).
+ * Int value. The minimum amount of time to hold on to a container that is idle. Only active when
+ * reuse is enabled. Set to -1 to never release idle containers (not recommended).
*/
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
public static final String TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MIN_MILLIS =
TEZ_AM_PREFIX + "container.idle.release-timeout-min.millis";
public static final long
- TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MIN_MILLIS_DEFAULT = 5000l;
+ TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MIN_MILLIS_DEFAULT = 5000l;
/**
* Int value. The maximum amount of time to hold on to a container if no task can be
@@ -1020,7 +1329,7 @@ public TezConfiguration(boolean loadDefaults) {
* TezConfiguration#TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MIN_MILLIS.
* Containers will have an expire time set to a random value between
* TezConfiguration#TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MIN_MILLIS &&
- * TezConfiguration#TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MAX_MILLIS. This
+ * TezConfiguration#TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MAX_MILLIS. This
* creates a graceful reduction in the amount of idle resources held
*/
@ConfigurationScope(Scope.AM)
@@ -1029,9 +1338,9 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_AM_PREFIX + "container.idle.release-timeout-max.millis";
public static final long
TEZ_AM_CONTAINER_IDLE_RELEASE_TIMEOUT_MAX_MILLIS_DEFAULT = 10000l;
-
+
/**
- * Int value. The minimum number of containers that will be held in session mode. Not active in
+ * Int value. The minimum number of containers that will be held in session mode. Not active in
* non-session mode. Enables an idle session (not running any DAG) to hold on to a minimum number
* of containers to provide fast response times for the next DAG.
*/
@@ -1042,7 +1351,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_AM_SESSION_MIN_HELD_CONTAINERS_DEFAULT = 0;
/**
- * Boolean value. Allow/disable logging for all dags in a session
+ * Boolean value. Allow/disable logging for all dags in a session
*/
@Private
@ConfigurationScope(Scope.AM)
@@ -1075,7 +1384,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final float TEZ_VERTEX_FAILURES_MAXPERCENT_DEFAULT = 0.0f;
/**
* Int value. The number of RM heartbeats to wait after preempting running tasks before preempting
- * more running tasks. After preempting a task, we need to wait at least 1 heartbeat so that the
+ * more running tasks. After preempting a task, we need to wait at least 1 heartbeat so that the
* RM can act on the released resources and assign new ones to us. Expert level setting.
*/
@ConfigurationScope(Scope.AM)
@@ -1086,8 +1395,8 @@ public TezConfiguration(boolean loadDefaults) {
/**
* Int value. Time (in millisecs) that an unsatisfied request will wait before preempting other
- * resources. In rare cases, the cluster says there are enough free resources but does not end
- * up getting enough on a node to actually assign it to the job. This configuration tries to put
+ * resources. In rare cases, the cluster says there are enough free resources but does not end
+ * up getting enough on a node to actually assign it to the job. This configuration tries to put
* a deadline on such wait to prevent indefinite job hangs.
*/
@ConfigurationScope(Scope.AM)
@@ -1125,7 +1434,7 @@ public TezConfiguration(boolean loadDefaults) {
*
* Specify additional user classpath information to be used for Tez AM and all containers.
* This will be appended to the classpath after PWD
- *
+ *
* 'tez.lib.uris.classpath' defines the relative classpath into the archives
* that are set in 'tez.lib.uris'
*
@@ -1151,7 +1460,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final String TEZ_AUX_URIS = TEZ_PREFIX + "aux.uris";
/**
- * Boolean value. Allows to ignore 'tez.lib.uris'. Useful during development as well as
+ * Boolean value. Allows to ignore 'tez.lib.uris'. Useful during development as well as
* raw Tez application where classpath is propagated with application
* via {@link LocalResource}s. This is mainly useful for developer/debugger scenarios.
*/
@@ -1217,8 +1526,8 @@ public TezConfiguration(boolean loadDefaults) {
/**
* Int value. Time (in seconds) to wait for AM to come up when trying to submit a DAG
- * from the client. Only relevant in session mode. If the cluster is busy and cannot launch the
- * AM then this timeout may be hit. In those case, using non-session mode is recommended if
+ * from the client. Only relevant in session mode. If the cluster is busy and cannot launch the
+ * AM then this timeout may be hit. In those case, using non-session mode is recommended if
* applicable. Otherwise increase the timeout (set to -1 for infinity. Not recommended)
*/
@ConfigurationScope(Scope.AM)
@@ -1389,7 +1698,7 @@ public TezConfiguration(boolean loadDefaults) {
public static final int TEZ_HISTORY_LOGGING_TIMELINE_NUM_DAGS_PER_GROUP_DEFAULT = 1;
/**
- * String value. The directory into which history data will be written. This defaults to the
+ * String value. The directory into which history data will be written. This defaults to the
* container logging directory. This is relevant only when SimpleHistoryLoggingService is being
* used for {@link TezConfiguration#TEZ_HISTORY_LOGGING_SERVICE_CLASS}
*/
@@ -1408,6 +1717,59 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_PREFIX + "simple.history.max.errors";
public static final int TEZ_SIMPLE_HISTORY_LOGGING_MAX_ERRORS_DEFAULT = 10;
+ /**
+ * String value. The base directory into which history data will be written when proto history
+ * logging service is used for {@link TezConfiguration#TEZ_HISTORY_LOGGING_SERVICE_CLASS}.
+ * If this is not set, then logging is disabled for ProtoHistoryLoggingService.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_HISTORY_LOGGING_PROTO_BASE_DIR =
+ TEZ_PREFIX + "history.logging.proto-base-dir";
+
+ /**
+ * Long value. The amount of time in seconds to wait to ensure all events for a day is synced
+ * to disk. This should be maximum time variation b/w machines + maximum time to sync file
+ * content and metadata.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_HISTORY_LOGGING_PROTO_SYNC_WINDOWN_SECS =
+ TEZ_PREFIX + "history.logging.proto-sync-window-secs";
+ public static final long TEZ_HISTORY_LOGGING_PROTO_SYNC_WINDOWN_SECS_DEFAULT = 60L;
+
+ /**
+ * Int value. Maximum queue size for proto history event logger.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="integer")
+ public static final String TEZ_HISTORY_LOGGING_PROTO_QUEUE_SIZE =
+ TEZ_PREFIX + "history.logging.queue.size";
+ public static final int TEZ_HISTORY_LOGGING_PROTO_QUEUE_SIZE_DEFAULT = 100000;
+
+
+ /**
+ * Boolean value. Set this to true, if the underlying file system does not support flush (Ex: s3).
+ * The dag submitted, initialized and started events are written into a file and closed. The rest
+ * of the events are written into another file.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_HISTORY_LOGGING_PROTO_SPLIT_DAG_START =
+ TEZ_PREFIX + "history.logging.split-dag-start";
+ public static final boolean TEZ_HISTORY_LOGGING_PROTO_SPLIT_DAG_START_DEFAULT = false;
+
+ /**
+ * Long value. The amount of time in seconds to wait to ensure all events for a day is synced
+ * to disk. This should be maximum time variation b/w machines + maximum time to sync file
+ * content and metadata.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_HISTORY_LOGGING_PROTO_DOAS =
+ TEZ_PREFIX + "history.logging.proto-doas";
+ public static final boolean TEZ_HISTORY_LOGGING_PROTO_DOAS_DEFAULT = false;
+
/**
* Int value. Time, in milliseconds, to wait while flushing YARN ATS data during shutdown.
* Expert level setting.
@@ -1466,7 +1828,7 @@ public TezConfiguration(boolean loadDefaults) {
+ "yarn.ats.acl.dag.domain.id";
/**
- * Boolean value. Enable recovery of DAGs. This allows a restarted app master to recover the
+ * Boolean value. Enable recovery of DAGs. This allows a restarted app master to recover the
* incomplete DAGs from the previous instance of the app master.
*/
@ConfigurationScope(Scope.AM)
@@ -1475,6 +1837,18 @@ public TezConfiguration(boolean loadDefaults) {
TEZ_PREFIX + "dag.recovery.enabled";
public static final boolean DAG_RECOVERY_ENABLED_DEFAULT = true;
+
+ /**
+ * Boolean value. When set, this enables AM to fail when DAG recovery is enabled and
+ * restarted app master did not find anything to recover
+ * Expert level setting.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_AM_FAILURE_ON_MISSING_RECOVERY_DATA =
+ TEZ_AM_PREFIX + "failure.on.missing.recovery.data";
+ public static final boolean TEZ_AM_FAILURE_ON_MISSING_RECOVERY_DATA_DEFAULT = false;
+
/**
* Int value. Size in bytes for the IO buffer size while processing the recovery file.
* Expert level setting.
@@ -1514,6 +1888,28 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean TEZ_LOCAL_MODE_DEFAULT = false;
+ /**
+ * Boolean value. Enable local mode execution in Tez without using network for communicating with
+ * DAGAppMaster. This option only makes sense when {@link #TEZ_LOCAL_MODE} is true. When
+ * TEZ_LOCAL_MODE_WITHOUT_NETWORK is turned on, LocalClient will call DAGAppMaster's methods
+ * directly.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type = "boolean")
+ public static final String TEZ_LOCAL_MODE_WITHOUT_NETWORK =
+ TEZ_PREFIX + "local.mode.without.network";
+
+ public static final boolean TEZ_LOCAL_MODE_WITHOUT_NETWORK_DEFAULT = false;
+
+ /**
+ * String value. TezLocalCacheManager uses this folder as a root for temp and localized files.
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_LOCAL_CACHE_ROOT_FOLDER = TEZ_PREFIX + "local.cache.root.folder";
+
+ public static final String TEZ_LOCAL_CACHE_ROOT_FOLDER_DEFAULT = ".";
+
/**
* Tez AM Inline Mode flag. Not valid till Tez-684 get checked-in
*/
@@ -1531,7 +1927,7 @@ public TezConfiguration(boolean loadDefaults) {
/**
* Int value.
- * The maximium number of tasks running in parallel within the app master process.
+ * The maximum number of tasks running in parallel within the app master process.
*/
@ConfigurationScope(Scope.AM)
@ConfigurationProperty(type="integer")
@@ -1565,10 +1961,10 @@ public TezConfiguration(boolean loadDefaults) {
public static final boolean TEZ_AM_ACLS_ENABLED_DEFAULT = true;
/**
- * String value.
+ * String value.
* AM view ACLs. This allows the specified users/groups to view the status of the AM and all DAGs
* that run within this AM.
- * Comma separated list of users, followed by whitespace, followed by a comma separated list of
+ * Comma separated list of users, followed by whitespace, followed by a comma separated list of
* groups
*/
@ConfigurationScope(Scope.AM)
@@ -1579,7 +1975,7 @@ public TezConfiguration(boolean loadDefaults) {
* String value.
* AM modify ACLs. This allows the specified users/groups to run modify operations on the AM
* such as submitting DAGs, pre-warming the session, killing DAGs or shutting down the session.
- * Comma separated list of users, followed by whitespace, followed by a comma separated list of
+ * Comma separated list of users, followed by whitespace, followed by a comma separated list of
* groups
*/
@ConfigurationScope(Scope.AM)
@@ -1652,13 +2048,23 @@ public TezConfiguration(boolean loadDefaults) {
+ "tez-ui.webservice.enable";
public static final boolean TEZ_AM_WEBSERVICE_ENABLE_DEFAULT = true;
+ /**
+ * String value. Range of ports that the AM can use for the WebUIService. Leave blank
+ * to use all possible ports. Expert level setting. It's hadoop standard range configuration.
+ * For example 50000-50050,50100-50200
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty(type="boolean")
+ public static final String TEZ_AM_WEBSERVICE_PORT_RANGE = TEZ_AM_PREFIX
+ + "tez-ui.webservice.port-range";
+
+ public static final String TEZ_AM_WEBSERVICE_PORT_RANGE_DEFAULT = "50000-50050";
+
// TODO only validate property here, value can also be validated if necessary
public static void validateProperty(String property, Scope usedScope) {
Scope validScope = PropertyScope.get(property);
if (validScope == null) {
- if (LOG.isDebugEnabled()) {
- LOG.debug(property + " is not standard configuration property of tez, can not been validated");
- }
+ LOG.debug("{} is not standard configuration property of tez, can not been validated", property);
} else {
if (usedScope.ordinal() > validScope.ordinal()) {
throw new IllegalStateException(property + " is set at the scope of " + usedScope
@@ -1693,6 +2099,18 @@ static Set getPropertySet() {
TEZ_PREFIX + "test.minicluster.app.wait.on.shutdown.secs";
public static final long TEZ_TEST_MINI_CLUSTER_APP_WAIT_ON_SHUTDOWN_SECS_DEFAULT = 30;
+ /**
+ * Long value
+ * Status Cache timeout window in minutes for the DAGClient.
+ */
+ @Private
+ @ConfigurationScope(Scope.CLIENT)
+ @ConfigurationProperty(type="long")
+ public static final String TEZ_CLIENT_DAG_STATUS_CACHE_TIMEOUT_SECS = TEZ_PREFIX
+ + "client.dag.status.cache.timeout-secs";
+ // Default timeout is 60 seconds.
+ public static final long TEZ_CLIENT_DAG_STATUS_CACHE_TIMEOUT_SECS_DEFAULT = 60;
+
/**
* Long value
* Time to wait (in milliseconds) for yarn app's diagnotics is available
@@ -1857,4 +2275,58 @@ static Set getPropertySet() {
public static final String TEZ_SHARED_EXECUTOR_MAX_THREADS = "tez.shared-executor.max-threads";
public static final int TEZ_SHARED_EXECUTOR_MAX_THREADS_DEFAULT = -1;
+ /**
+ * Acquire all FileSystems info. e.g., all namenodes info of HDFS federation cluster.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_JOB_FS_SERVERS = "tez.job.fs-servers";
+
+ /**
+ * Skip delegation token renewal for specified FileSystems.
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_JOB_FS_SERVERS_TOKEN_RENEWAL_EXCLUDE = "tez.job.fs-servers.token-renewal.exclude";
+
+ /**
+ * Comma-separated list of properties that MRReaderMapred should return (if present) when calling for config updates.
+ */
+ @ConfigurationScope(Scope.VERTEX)
+ @ConfigurationProperty
+ public static final String TEZ_MRREADER_CONFIG_UPDATE_PROPERTIES = "tez.mrreader.config.update.properties";
+
+ /**
+ * Frequency at which thread dump should be captured. Supports TimeUnits. This is effective only
+ * when org.apache.tez.dag.app.ThreadDumpDAGHook is configured to tez.am.hooks or
+ * org.apache.tez.runtime.task.ThreadDumpTaskAttemptHook is configured to tez.task.attempt.hooks.
+ */
+ @ConfigurationScope(Scope.DAG)
+ @ConfigurationProperty
+ public static final String TEZ_THREAD_DUMP_INTERVAL = "tez.thread.dump.interval";
+ public static final String TEZ_THREAD_DUMP_INTERVAL_DEFAULT = "100ms";
+
+ /**
+ * Limits the amount of data that can be written to LocalFileSystem by a Task.
+ */
+ @ConfigurationScope(Scope.DAG)
+ @ConfigurationProperty(type = "long")
+ public static final String TEZ_TASK_LOCAL_FS_WRITE_LIMIT_BYTES = "tez.task.local-fs.write-limit.bytes";
+ public static final long TEZ_TASK_LOCAL_FS_WRITE_LIMIT_BYTES_DEFAULT = -1;
+
+ /**
+ * Comma-separated list of hook classes implementing org.apache.tez.runtime.hook.TezDAGHook.
+ * e.g. org.apache.tez.dag.app.ThreadDumpDAGHook
+ */
+ @ConfigurationScope(Scope.AM)
+ @ConfigurationProperty
+ public static final String TEZ_AM_HOOKS = TEZ_AM_PREFIX + "hooks";
+
+ /**
+ * Comma-separated list of hook classes implementing org.apache.tez.runtime.hook.TezTaskAttemptHook.
+ * e.g. org.apache.tez.runtime.task.ThreadDumpTaskAttemptHook
+ */
+ @ConfigurationScope(Scope.DAG)
+ @ConfigurationProperty
+ public static final String TEZ_TASK_ATTEMPT_HOOKS = TEZ_TASK_PREFIX + "attempt.hooks";
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/TezConfigurationConstants.java b/tez-api/src/main/java/org/apache/tez/dag/api/TezConfigurationConstants.java
index 33abc77de4..4bd5e254fb 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/TezConfigurationConstants.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/TezConfigurationConstants.java
@@ -27,12 +27,14 @@
*/
@ConfigurationClass(templateFileName = "tez-conf-constants.xml")
@Private
-public class TezConfigurationConstants {
+public final class TezConfigurationConstants {
static {
TezConfiguration.setupConfigurationScope(TezConfigurationConstants.class);
}
+ private TezConfigurationConstants() {}
+
/**
* String value. Set automatically by the client. The host name of the client the Tez application
* was submitted from.
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/TezConstants.java b/tez-api/src/main/java/org/apache/tez/dag/api/TezConstants.java
index cf5ab11ec7..379eb0cb1b 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/TezConstants.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/TezConstants.java
@@ -24,7 +24,7 @@
* Specifies all constant values in Tez
*/
@Private
-public class TezConstants {
+public final class TezConstants {
public static final String TEZ_APPLICATION_MASTER_CLASS =
@@ -129,4 +129,5 @@ public static String getTezUberServicePluginName() {
public static final double TEZ_CONTAINER_MAX_JAVA_HEAP_FRACTION_SMALL_SLAB = 0.7;
public static final double TEZ_CONTAINER_MAX_JAVA_HEAP_FRACTION_LARGE_SLAB = 0.8;
+ private TezConstants() {}
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/UserPayload.java b/tez-api/src/main/java/org/apache/tez/dag/api/UserPayload.java
index fa617b5317..087b17ab9d 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/UserPayload.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/UserPayload.java
@@ -62,6 +62,17 @@ public static UserPayload create(@Nullable ByteBuffer payload, int version) {
return new UserPayload(payload, version);
}
+ /**
+ * Return the payload as a ByteBuffer.
+ * @return ByteBuffer.
+ */
+ @Nullable
+ public ByteBuffer getRawPayload() {
+ // Note: Several bits of serialization, including deepCopyAsArray depend on a new instance of the
+ // ByteBuffer being returned, since they modify it. If changing this code to return the same
+ // ByteBuffer - deepCopyAsArray and TezEntityDescriptor need to be looked at.
+ return payload == EMPTY_BYTE ? null : payload.duplicate();
+ }
/**
* Return the payload as a read-only ByteBuffer.
* @return read-only ByteBuffer.
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/Vertex.java b/tez-api/src/main/java/org/apache/tez/dag/api/Vertex.java
index bf3a59ba24..8ce3fb67e6 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/Vertex.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/Vertex.java
@@ -23,6 +23,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.classification.InterfaceAudience;
@@ -35,7 +36,7 @@
import org.apache.tez.dag.api.VertexGroup.GroupInfo;
import org.apache.tez.runtime.api.LogicalIOProcessor;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -276,10 +277,10 @@ public Map getTaskLocalFiles() {
* set environment for all vertices via Tezconfiguration#TEZ_TASK_LAUNCH_ENV
* @param environment
* @return this Vertex
+ * NullPointerException if {@code environment} is {@code null}
*/
public Vertex setTaskEnvironment(Map environment) {
- Preconditions.checkArgument(environment != null);
- this.taskEnvironment.putAll(environment);
+ this.taskEnvironment.putAll(Objects.requireNonNull(environment));
return this;
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/VertexManagerPluginContext.java b/tez-api/src/main/java/org/apache/tez/dag/api/VertexManagerPluginContext.java
index b858a6531a..0862f49034 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/VertexManagerPluginContext.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/VertexManagerPluginContext.java
@@ -21,6 +21,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
@@ -31,9 +32,10 @@
import org.apache.tez.dag.api.event.VertexState;
import org.apache.tez.runtime.api.InputSpecUpdate;
import org.apache.tez.runtime.api.VertexStatistics;
+import org.apache.tez.runtime.api.events.CustomProcessorEvent;
import org.apache.tez.runtime.api.events.InputDataInformationEvent;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
/**
* Object with API's to interact with the Tez execution engine
@@ -70,8 +72,7 @@ public class TaskWithLocationHint {
Integer taskIndex;
TaskLocationHint locationHint;
public TaskWithLocationHint(Integer taskIndex, @Nullable TaskLocationHint locationHint) {
- Preconditions.checkState(taskIndex != null);
- this.taskIndex = taskIndex;
+ this.taskIndex = Objects.requireNonNull(taskIndex);
this.locationHint = locationHint;
}
@@ -268,6 +269,17 @@ public void reconfigureVertex(@Nullable Map rootInputSp
* task to which events need to be sent.
*/
public void addRootInputEvents(String inputName, Collection events);
+
+ /**
+ * Allows a VertexManagerPlugin to send events of custom payload to processor
+ * of a specific task of managed vertex
+ *
+ * It's up to user to make sure taskId is valid
+ *
+ * @param events events to be sent
+ * @param taskId id of a task of managed vertex
+ */
+ public void sendEventToProcessor(Collection events, int taskId);
@Deprecated
/**
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClient.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClient.java
index c70da75c9e..944bff3fbd 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClient.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClient.java
@@ -103,7 +103,7 @@ public abstract VertexStatus getVertexStatus(String vertexName,
public abstract void tryKillDAG() throws IOException, TezException;
/**
- * Wait for DAG to complete without printing any vertex statuses
+ * Wait forever for DAG to complete without printing any vertex statuses
*
* @return Final DAG Status
* @throws IOException
@@ -112,6 +112,20 @@ public abstract VertexStatus getVertexStatus(String vertexName,
*/
public abstract DAGStatus waitForCompletion() throws IOException, TezException, InterruptedException;
+ /**
+ * Wait for DAG to complete without printing any vertex statuses
+ *
+ * @param timeMs Maximum wait duration
+ * @return Final DAG Status, or null on timeout or if DAG is no longer running
+ * @throws IOException
+ * @throws TezException
+ * @throws InterruptedException
+ */
+ public DAGStatus waitForCompletion(long timeMs) throws IOException, TezException, InterruptedException {
+ // Make non-abstract to avoid compat issues in Hive.
+ throw new UnsupportedOperationException();
+ }
+
/**
* Wait for DAG to complete and periodically print *all* vertices' status.
*
@@ -125,4 +139,14 @@ public abstract VertexStatus getVertexStatus(String vertexName,
*/
public abstract DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set statusGetOpts)
throws IOException, TezException, InterruptedException;
+
+ /**
+ * Returns the Tez AM's web ui address if any.
+ *
+ * @return The http web UI address
+ * @throws IOException
+ * @throws TezException
+ */
+ public abstract String getWebUIAddress() throws IOException, TezException;
+
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImpl.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImpl.java
index 1cf0bfcd82..2913d08c41 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImpl.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImpl.java
@@ -19,6 +19,7 @@
package org.apache.tez.dag.api.client;
import javax.annotation.Nullable;
+
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Collections;
@@ -26,11 +27,13 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.tez.common.CachedEntity;
+import org.apache.tez.common.Preconditions;
import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,11 +42,11 @@
import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.tez.client.FrameworkClient;
import org.apache.tez.common.counters.TezCounters;
import org.apache.tez.dag.api.DAGNotRunningException;
+import org.apache.tez.dag.api.NoCurrentDAGException;
import org.apache.tez.dag.api.TezConfiguration;
import org.apache.tez.dag.api.TezException;
import org.apache.tez.dag.api.TezUncheckedException;
@@ -58,13 +61,15 @@ public class DAGClientImpl extends DAGClient {
private final String dagId;
private final TezConfiguration conf;
private final FrameworkClient frameworkClient;
-
+ /**
+ * Container to cache the last {@link DAGStatus}.
+ */
+ private final CachedEntity cachedDAGStatusRef;
@VisibleForTesting
protected DAGClientInternal realClient;
- private boolean dagCompleted = false;
+ private volatile boolean dagCompleted = false;
@VisibleForTesting
protected boolean isATSEnabled = false;
- private DAGStatus cachedDagStatus = null;
Map cachedVertexStatus = new HashMap();
private static final long SLEEP_FOR_COMPLETION = 500;
@@ -79,7 +84,7 @@ public class DAGClientImpl extends DAGClient {
private boolean cleanupFrameworkClient;
public DAGClientImpl(ApplicationId appId, String dagId, TezConfiguration conf,
- YarnConfiguration yarnConf, @Nullable FrameworkClient frameworkClient) {
+ @Nullable FrameworkClient frameworkClient, UserGroupInformation ugi) {
this.appId = appId;
this.dagId = dagId;
this.conf = conf;
@@ -87,7 +92,7 @@ public DAGClientImpl(ApplicationId appId, String dagId, TezConfiguration conf,
this.frameworkClient = frameworkClient;
} else {
this.frameworkClient = FrameworkClient.createFrameworkClient(conf);
- this.frameworkClient.init(conf, yarnConf);
+ this.frameworkClient.init(conf);
this.frameworkClient.start();
cleanupFrameworkClient = true;
}
@@ -99,7 +104,7 @@ public DAGClientImpl(ApplicationId appId, String dagId, TezConfiguration conf,
TezConfiguration.TEZ_AM_HISTORY_LOGGING_ENABLED_DEFAULT) &&
DAGClientTimelineImpl.isSupported();
- realClient = new DAGClientRPCImpl(appId, dagId, conf, this.frameworkClient);
+ realClient = new DAGClientRPCImpl(appId, dagId, conf, this.frameworkClient, ugi);
statusPollInterval = conf.getLong(
TezConfiguration.TEZ_DAG_STATUS_POLLINTERVAL_MS,
TezConfiguration.TEZ_DAG_STATUS_POLLINTERVAL_MS_DEFAULT);
@@ -110,6 +115,28 @@ public DAGClientImpl(ApplicationId appId, String dagId, TezConfiguration conf,
this.diagnoticsWaitTimeout = conf.getLong(
TezConfiguration.TEZ_CLIENT_DIAGNOSTICS_WAIT_TIMEOUT_MS,
TezConfiguration.TEZ_CLIENT_DIAGNOSTICS_WAIT_TIMEOUT_MS_DEFAULT);
+ cachedDAGStatusRef = initCacheDAGRefFromConf(conf);
+ }
+
+ /**
+ * Constructs a new {@link CachedEntity} for {@link DAGStatus}.
+ * @param tezConf TEZ configuration parameters.
+ * @return a caching entry to hold the {@link DAGStatus}.
+ */
+ protected CachedEntity initCacheDAGRefFromConf(TezConfiguration tezConf) {
+ long clientDAGStatusCacheTimeOut = tezConf.getLong(
+ TezConfiguration.TEZ_CLIENT_DAG_STATUS_CACHE_TIMEOUT_SECS,
+ TezConfiguration.TEZ_CLIENT_DAG_STATUS_CACHE_TIMEOUT_SECS_DEFAULT);
+ if (clientDAGStatusCacheTimeOut <= 0) {
+ LOG.error("DAG Status cache timeout interval should be positive. Enforcing default value.");
+ clientDAGStatusCacheTimeOut =
+ TezConfiguration.TEZ_CLIENT_DAG_STATUS_CACHE_TIMEOUT_SECS_DEFAULT;
+ }
+ return new CachedEntity<>(TimeUnit.SECONDS, clientDAGStatusCacheTimeOut);
+ }
+
+ protected CachedEntity getCachedDAGStatusRef() {
+ return cachedDAGStatusRef;
}
@Override
@@ -133,13 +160,11 @@ public DAGStatus getDAGStatus(@Nullable Set statusOptions,
}
long startTime = System.currentTimeMillis();
- boolean refreshStatus;
- DAGStatus dagStatus;
- if(cachedDagStatus != null) {
- dagStatus = cachedDagStatus;
- refreshStatus = true;
- } else {
- // For the first lookup only. After this cachedDagStatus should be populated.
+
+ DAGStatus dagStatus = cachedDAGStatusRef.getValue();
+ boolean refreshStatus = true;
+ if (dagStatus == null) {
+ // the first lookup only or when the cachedDAG has expired
dagStatus = getDAGStatus(statusOptions);
refreshStatus = false;
}
@@ -209,7 +234,7 @@ public DAGStatus getDAGStatus(@Nullable Set statusOptions,
}
}
- private DAGStatus getDAGStatusInternal(@Nullable Set statusOptions,
+ protected DAGStatus getDAGStatusInternal(@Nullable Set statusOptions,
long timeout) throws TezException, IOException {
if (!dagCompleted) {
@@ -221,13 +246,14 @@ private DAGStatus getDAGStatusInternal(@Nullable Set statusOption
final DAGStatus dagStatus = getDAGStatusViaAM(statusOptions, timeout);
if (!dagCompleted) {
- if (dagStatus != null) {
- cachedDagStatus = dagStatus;
+ if (dagStatus != null) { // update the cached DAGStatus
+ cachedDAGStatusRef.setValue(dagStatus);
return dagStatus;
}
- if (cachedDagStatus != null) {
+ DAGStatus cachedDAG = cachedDAGStatusRef.getValue();
+ if (cachedDAG != null) {
// could not get from AM (not reachable/ was killed). return cached status.
- return cachedDagStatus;
+ return cachedDAG;
}
}
@@ -247,16 +273,17 @@ private DAGStatus getDAGStatusInternal(@Nullable Set statusOption
LOG.info("Failed to fetch DAG data for completed DAG from YARN Timeline"
+ " - Application not found by YARN", e);
} catch (TezException e) {
- if (LOG.isDebugEnabled()) {
- LOG.info("DAGStatus fetch failed." + e.getMessage());
- }
+ LOG.debug("DAGStatus fetch failed", e);
}
}
// dag completed and Timeline service is either not enabled or does not have completion status
// return cached status if completion info is present.
- if (dagCompleted && cachedDagStatus != null && cachedDagStatus.isCompleted()) {
- return cachedDagStatus;
+ if (dagCompleted) {
+ DAGStatus cachedDag = cachedDAGStatusRef.getValue();
+ if (cachedDag != null && cachedDag.isCompleted()) {
+ return cachedDag;
+ }
}
// everything else fails rely on RM.
@@ -270,9 +297,13 @@ public DAGStatus getDAGStatus(@Nullable Set statusOptions) throws
}
@Override
- public VertexStatus getVertexStatus(String vertexName, Set statusOptions) throws
- IOException, TezException {
+ public VertexStatus getVertexStatus(String vertexName, Set statusOptions)
+ throws IOException, TezException {
+ return getVertexStatusInternal(statusOptions, vertexName);
+ }
+ protected VertexStatus getVertexStatusInternal(Set statusOptions, String vertexName)
+ throws IOException, TezException {
if (!dagCompleted) {
VertexStatus vertexStatus = getVertexStatusViaAM(vertexName, statusOptions);
@@ -302,9 +333,7 @@ public VertexStatus getVertexStatus(String vertexName, Set status
+ " - Application not found by YARN", e);
return null;
} catch (TezException e) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("ERROR fetching vertex data from Yarn Timeline. " + e.getMessage());
- }
+ LOG.debug("ERROR fetching vertex data from Yarn Timeline", e);
}
}
@@ -337,16 +366,21 @@ public void tryKillDAG() throws IOException, TezException {
}
}
+ @Override
+ public DAGStatus waitForCompletion(long timeMs) throws IOException, TezException, InterruptedException {
+ return _waitForCompletionWithStatusUpdates(timeMs, false, EnumSet.noneOf(StatusGetOpts.class));
+ }
+
@Override
public DAGStatus waitForCompletion() throws IOException, TezException, InterruptedException {
- return _waitForCompletionWithStatusUpdates(false, EnumSet.noneOf(StatusGetOpts.class));
+ return _waitForCompletionWithStatusUpdates(-1, false, EnumSet.noneOf(StatusGetOpts.class));
}
@Override
public DAGStatus waitForCompletionWithStatusUpdates(
@Nullable Set statusGetOpts) throws IOException, TezException,
InterruptedException {
- return _waitForCompletionWithStatusUpdates(true, statusGetOpts);
+ return _waitForCompletionWithStatusUpdates(-1, true, statusGetOpts);
}
@Override
@@ -375,10 +409,21 @@ private DAGStatus getDAGStatusViaAM(@Nullable Set statusOptions,
} catch (ApplicationNotFoundException e) {
LOG.info("DAG is no longer running - application not found by YARN", e);
dagCompleted = true;
+ } catch (NoCurrentDAGException e) {
+ if (conf.getBoolean(TezConfiguration.DAG_RECOVERY_ENABLED,
+ TezConfiguration.DAG_RECOVERY_ENABLED_DEFAULT)) {
+ LOG.info("Got NoCurrentDAGException from AM, going on as recovery is enabled", e);
+ } else {
+ // if recovery is disabled, we're not expecting the DAG to be finished any time in the future
+ LOG.info("Got NoCurrentDAGException from AM, returning a failed DAG as recovery is disabled", e);
+ return dagLost();
+ }
} catch (TezException e) {
- // can be either due to a n/w issue of due to AM completed.
+ // can be either due to a n/w issue or due to AM completed.
+ LOG.info("Cannot retrieve DAG Status due to TezException: {}", e.getMessage());
} catch (IOException e) {
- // can be either due to a n/w issue of due to AM completed.
+ // can be either due to a n/w issue or due to AM completed.
+ LOG.info("Cannot retrieve DAG Status due to IOException: {}", e.getMessage());
}
if (dagStatus == null && !dagCompleted) {
@@ -388,6 +433,14 @@ private DAGStatus getDAGStatusViaAM(@Nullable Set statusOptions,
return dagStatus;
}
+ private DAGStatus dagLost() {
+ DAGProtos.DAGStatusProto.Builder builder = DAGProtos.DAGStatusProto.newBuilder();
+ DAGStatus dagStatus = new DAGStatus(builder, DagStatusSource.AM);
+ builder.setState(DAGProtos.DAGStatusStateProto.DAG_FAILED);
+ builder.addAllDiagnostics(Collections.singleton(NoCurrentDAGException.MESSAGE_PREFIX));
+ return dagStatus;
+ }
+
private VertexStatus getVertexStatusViaAM(String vertexName, Set statusOptions) throws
IOException {
VertexStatus vertexStatus = null;
@@ -400,9 +453,11 @@ private VertexStatus getVertexStatusViaAM(String vertexName, Set
LOG.info("DAG is no longer running - application not found by YARN", e);
dagCompleted = true;
} catch (TezException e) {
- // can be either due to a n/w issue of due to AM completed.
+ // can be either due to a n/w issue or due to AM completed.
+ LOG.info("Cannot retrieve Vertex Status due to TezException: {}", e.getMessage());
} catch (IOException e) {
// can be either due to a n/w issue of due to AM completed.
+ LOG.info("Cannot retrieve Vertex Status due to IOException: {}", e.getMessage());
}
if (vertexStatus == null && !dagCompleted) {
@@ -420,12 +475,11 @@ private VertexStatus getVertexStatusViaAM(String vertexName, Set
*/
@VisibleForTesting
protected DAGStatus getDAGStatusViaRM() throws TezException, IOException {
- if(LOG.isDebugEnabled()) {
- LOG.debug("GetDAGStatus via AM for app: " + appId + " dag:" + dagId);
- }
+ LOG.debug("Get DAG status via framework client for app: {} dag: {}", appId, dagId);
ApplicationReport appReport;
try {
appReport = frameworkClient.getApplicationReport(appId);
+ LOG.debug("Got appReport from framework client: {}", appReport);
} catch (ApplicationNotFoundException e) {
LOG.info("DAG is no longer running - application not found by YARN", e);
throw new DAGNotRunningException(e);
@@ -504,15 +558,21 @@ protected DAGStatus getDAGStatusViaRM() throws TezException, IOException {
return dagStatus;
}
- private DAGStatus _waitForCompletionWithStatusUpdates(boolean vertexUpdates,
+ private DAGStatus _waitForCompletionWithStatusUpdates(long timeMs,
+ boolean vertexUpdates,
@Nullable Set statusGetOpts) throws IOException, TezException, InterruptedException {
DAGStatus dagStatus;
boolean initPrinted = false;
boolean runningPrinted = false;
double dagProgress = -1.0; // Print the first one
// monitoring
+ Long maxNs = timeMs >= 0 ? (System.nanoTime() + (timeMs * 1000000L)) : null;
while (true) {
- dagStatus = getDAGStatus(statusGetOpts, SLEEP_FOR_COMPLETION);
+ try {
+ dagStatus = getDAGStatus(statusGetOpts, SLEEP_FOR_COMPLETION);
+ } catch (DAGNotRunningException ex) {
+ return null;
+ }
if (!initPrinted
&& (dagStatus.getState() == DAGStatus.State.INITING || dagStatus.getState() == DAGStatus.State.SUBMITTED)) {
initPrinted = true; // Print once
@@ -525,6 +585,9 @@ private DAGStatus _waitForCompletionWithStatusUpdates(boolean vertexUpdates,
|| dagStatus.getState() == DAGStatus.State.ERROR) {
break;
}
+ if (maxNs != null && System.nanoTime() > maxNs) {
+ return null;
+ }
}// End of while(true)
Set vertexNames = Collections.emptySet();
@@ -537,7 +600,14 @@ private DAGStatus _waitForCompletionWithStatusUpdates(boolean vertexUpdates,
vertexNames = getDAGStatus(statusGetOpts).getVertexProgress().keySet();
}
dagProgress = monitorProgress(vertexNames, dagProgress, null, dagStatus);
- dagStatus = getDAGStatus(statusGetOpts, SLEEP_FOR_COMPLETION);
+ try {
+ dagStatus = getDAGStatus(statusGetOpts, SLEEP_FOR_COMPLETION);
+ } catch (DAGNotRunningException ex) {
+ return null;
+ }
+ if (maxNs != null && System.nanoTime() > maxNs) {
+ return null;
+ }
}// end of while
// Always print the last status irrespective of progress change
monitorProgress(vertexNames, -1.0, statusGetOpts, dagStatus);
@@ -617,9 +687,7 @@ private void switchToTimelineClient() throws IOException, TezException {
realClient.close();
realClient = new DAGClientTimelineImpl(appId, dagId, conf, frameworkClient,
(int) (2 * PRINT_STATUS_INTERVAL_MILLIS));
- if (LOG.isDebugEnabled()) {
- LOG.debug("dag completed switching to DAGClientTimelineImpl");
- }
+ LOG.debug("dag completed switching to DAGClientTimelineImpl");
}
@VisibleForTesting
@@ -627,6 +695,11 @@ public DAGClientInternal getRealClient() {
return realClient;
}
+ @Override
+ public String getWebUIAddress() throws IOException, TezException {
+ return realClient.getWebUIAddress();
+ }
+
private double getProgress(Progress progress) {
return (progress.getTotalTaskCount() == 0 ? 0.0 : (double) (progress.getSucceededTaskCount())
/ progress.getTotalTaskCount());
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImplLocal.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImplLocal.java
new file mode 100644
index 0000000000..851bb687a1
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientImplLocal.java
@@ -0,0 +1,62 @@
+/**
+ * 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.tez.dag.api.client;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+import javax.annotation.Nullable;
+
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.tez.client.FrameworkClient;
+import org.apache.tez.dag.api.TezConfiguration;
+import org.apache.tez.dag.api.TezException;
+
+/**
+ * A DAGClientImpl which is typically used for tez.local.mode.without.network=true.
+ */
+public class DAGClientImplLocal extends DAGClientImpl {
+
+ private BiFunction, Long, DAGStatus> dagStatusFunction;
+ private BiFunction, String, VertexStatus> vertexStatusFunction;
+
+ public DAGClientImplLocal(ApplicationId appId, String dagId, TezConfiguration conf,
+ FrameworkClient frameworkClient, UserGroupInformation ugi,
+ BiFunction, Long, DAGStatus> dagStatusFunction,
+ BiFunction, String, VertexStatus> vertexStatusFunction) {
+ super(appId, dagId, conf, frameworkClient, ugi);
+ this.dagStatusFunction = dagStatusFunction;
+ this.vertexStatusFunction = vertexStatusFunction;
+ }
+
+ @Override
+ protected DAGStatus getDAGStatusInternal(@Nullable Set statusOptions, long timeout)
+ throws TezException, IOException {
+ return dagStatusFunction.apply(statusOptions == null ? new HashSet<>() : statusOptions,
+ timeout);
+ }
+
+ @Override
+ protected VertexStatus getVertexStatusInternal(@Nullable Set statusOptions, String vertexName)
+ throws TezException, IOException {
+ return vertexStatusFunction.apply(statusOptions == null ? new HashSet<>() : statusOptions, vertexName);
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientInternal.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientInternal.java
index a3c898a855..8346d53da7 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientInternal.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientInternal.java
@@ -125,4 +125,6 @@ public abstract VertexStatus getVertexStatus(String vertexName,
*/
public abstract DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set statusGetOpts)
throws IOException, TezException, InterruptedException;
+
+ public abstract String getWebUIAddress() throws IOException, TezException;
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientTimelineImpl.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientTimelineImpl.java
index d34dbf008d..4ec9c94354 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientTimelineImpl.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGClientTimelineImpl.java
@@ -213,6 +213,9 @@ public void close() throws IOException {
httpClient.destroy();
httpClient = null;
}
+ if (timelineReaderStrategy != null) {
+ timelineReaderStrategy.close();
+ }
}
private DAGStatusProto.Builder parseDagStatus(JSONObject jsonRoot, Set statusOptions)
@@ -520,4 +523,9 @@ public DAGStatus getDAGStatus(@Nullable Set statusOptions,
return getDAGStatus(statusOptions);
}
+ @Override
+ public String getWebUIAddress() throws IOException, TezException {
+ throw new TezException("DAGClientTimelineImpl.getWebUIAddress is not supported");
+ }
+
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGStatus.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGStatus.java
index cbf641e00f..1f8db62b80 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGStatus.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/DAGStatus.java
@@ -152,6 +152,14 @@ public TezCounters getDAGCounters() {
return dagCounters;
}
+ public long getMemoryUsedByAM() {
+ return proxy.getMemoryUsedByAM();
+ }
+
+ public long getMemoryUsedByTasks() {
+ return proxy.getMemoryUsedByTasks();
+ }
+
@InterfaceAudience.Private
DagStatusSource getSource() {
return this.source;
@@ -201,12 +209,12 @@ public int hashCode() {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("status=" + getState()
- + ", progress=" + getDAGProgress()
- + ", diagnostics="
- + StringUtils.join(getDiagnostics(), LINE_SEPARATOR)
- + ", counters="
- + (getDAGCounters() == null ? "null" : getDAGCounters().toString()));
+ sb.append("status=" + getState());
+ sb.append(", progress=" + getDAGProgress());
+ sb.append(", diagnostics=" + StringUtils.join(getDiagnostics(), LINE_SEPARATOR));
+ sb.append(", memoryUsedByAM=").append(proxy.getMemoryUsedByAM());
+ sb.append(", memoryUsedByTasks=").append(proxy.getMemoryUsedByTasks());
+ sb.append(", counters=" + (getDAGCounters() == null ? "null" : getDAGCounters().toString()));
return sb.toString();
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/Progress.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/Progress.java
index 110ac90d8d..656838dc5a 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/Progress.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/Progress.java
@@ -63,6 +63,10 @@ public int getKilledTaskAttemptCount() {
return proxy.getKilledTaskAttemptCount();
}
+ public int getRejectedTaskAttemptCount() {
+ return proxy.getRejectedTaskAttemptCount();
+ }
+
@Override
public boolean equals(Object obj) {
if (obj instanceof Progress){
@@ -73,7 +77,8 @@ && getRunningTaskCount() == other.getRunningTaskCount()
&& getFailedTaskCount() == other.getFailedTaskCount()
&& getKilledTaskCount() == other.getKilledTaskCount()
&& getFailedTaskAttemptCount() == other.getFailedTaskAttemptCount()
- && getKilledTaskAttemptCount() == other.getKilledTaskAttemptCount();
+ && getKilledTaskAttemptCount() == other.getKilledTaskAttemptCount()
+ && getRejectedTaskAttemptCount() == other.getRejectedTaskAttemptCount();
}
return false;
}
@@ -94,6 +99,8 @@ public int hashCode() {
getFailedTaskAttemptCount();
result = prime * result +
getKilledTaskAttemptCount();
+ result = prime * result +
+ getRejectedTaskAttemptCount();
return result;
}
@@ -119,6 +126,10 @@ public String toString() {
sb.append(" KilledTaskAttempts: ");
sb.append(getKilledTaskAttemptCount());
}
+ if (getRejectedTaskAttemptCount() > 0) {
+ sb.append(" RejectedTaskAttempts: ");
+ sb.append(getRejectedTaskAttemptCount());
+ }
return sb.toString();
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/StatusGetOpts.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/StatusGetOpts.java
index 1a9df7afa1..3518d33c2c 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/StatusGetOpts.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/StatusGetOpts.java
@@ -29,5 +29,6 @@
@Evolving
public enum StatusGetOpts {
/** Retrieve Counters with Status */
- GET_COUNTERS
+ GET_COUNTERS,
+ GET_MEMORY_USAGE
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/TimelineReaderFactory.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/TimelineReaderFactory.java
index c0569dda98..fec9191dec 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/TimelineReaderFactory.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/TimelineReaderFactory.java
@@ -54,14 +54,14 @@
* create a httpclient, configured for the appropriate runtime.
*
* on hadoop 2.6+ the factory returns TimelineReaderTokenAuthenticatedStrategy, which supports
- * kerberos based auth (secure cluster) or psuedo auth (un-secure cluster).
+ * kerberos based auth (secure cluster) or pseudo auth (un-secure cluster).
*
* on hadoop 2.4 where the token delegation auth is not supported, TimelineReaderPseudoAuthenticatedStrategy
* is used which supports only unsecure timeline.
*
*/
@InterfaceAudience.Private
-public class TimelineReaderFactory {
+public final class TimelineReaderFactory {
private static final Logger LOG = LoggerFactory.getLogger(TimelineReaderFactory.class);
@@ -79,6 +79,8 @@ public class TimelineReaderFactory {
private static Class> delegationTokenAuthenticatorClazz = null;
private static Method delegationTokenAuthenticateURLOpenConnectionMethod = null;
+ private TimelineReaderFactory() {}
+
public static TimelineReaderStrategy getTimelineReaderStrategy(Configuration conf,
boolean useHttps,
int connTimeout) throws TezException {
@@ -133,23 +135,24 @@ public static boolean isTimelineClientSupported() {
public interface TimelineReaderStrategy {
Client getHttpClient() throws IOException;
+ void close();
}
/*
* auth strategy for secured and unsecured environment with delegation token (hadoop 2.6 and above)
*/
private static class TimelineReaderTokenAuthenticatedStrategy implements TimelineReaderStrategy {
- private final Configuration conf;
private final boolean useHttps;
private final int connTimeout;
+ private final SSLFactory sslFactory;
public TimelineReaderTokenAuthenticatedStrategy(final Configuration conf,
final boolean useHttps,
final int connTimeout) {
- this.conf = conf;
this.useHttps = useHttps;
this.connTimeout = connTimeout;
+ this.sslFactory = useHttps ? new SSLFactory(CLIENT, conf) : null;
}
@Override
@@ -157,11 +160,10 @@ public Client getHttpClient() throws IOException {
Authenticator authenticator;
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
UserGroupInformation realUgi = ugi.getRealUser();
- UserGroupInformation authUgi;
String doAsUser;
ClientConfig clientConfig = new DefaultClientConfig(JSONRootElementProvider.App.class);
- ConnectionConfigurator connectionConfigurator = getNewConnectionConf(conf, useHttps,
- connTimeout);
+ ConnectionConfigurator connectionConfigurator = getNewConnectionConf(useHttps,
+ connTimeout, sslFactory);
try {
authenticator = getTokenAuthenticator();
@@ -171,17 +173,15 @@ public Client getHttpClient() throws IOException {
}
if (realUgi != null) {
- authUgi = realUgi;
doAsUser = ugi.getShortUserName();
} else {
- authUgi = ugi;
doAsUser = null;
}
HttpURLConnectionFactory connectionFactory;
try {
connectionFactory = new TokenAuthenticatedURLConnectionFactory(connectionConfigurator, authenticator,
- authUgi, doAsUser);
+ doAsUser);
} catch (TezException e) {
throw new IOException("Fail to create TokenAuthenticatedURLConnectionFactory", e);
}
@@ -204,17 +204,14 @@ private static class TokenAuthenticatedURLConnectionFactory implements HttpURLCo
private final Authenticator authenticator;
private final ConnectionConfigurator connConfigurator;
- private final UserGroupInformation authUgi;
private final String doAsUser;
private final AuthenticatedURL.Token token;
public TokenAuthenticatedURLConnectionFactory(ConnectionConfigurator connConfigurator,
Authenticator authenticator,
- UserGroupInformation authUgi,
String doAsUser) throws TezException {
this.connConfigurator = connConfigurator;
this.authenticator = authenticator;
- this.authUgi = authUgi;
this.doAsUser = doAsUser;
this.token = ReflectionUtils.createClazzInstance(
DELEGATION_TOKEN_AUTHENTICATED_URL_TOKEN_CLASS_NAME, null, null);
@@ -238,6 +235,13 @@ public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
}
}
}
+
+ @Override
+ public void close() {
+ if (sslFactory != null) {
+ sslFactory.destroy();
+ }
+ }
}
/*
@@ -247,19 +251,20 @@ public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
protected static class TimelineReaderPseudoAuthenticatedStrategy implements TimelineReaderStrategy {
private final ConnectionConfigurator connectionConf;
+ private final SSLFactory sslFactory;
public TimelineReaderPseudoAuthenticatedStrategy(final Configuration conf,
final boolean useHttps,
final int connTimeout) {
- connectionConf = getNewConnectionConf(conf, useHttps, connTimeout);
+ sslFactory = useHttps ? new SSLFactory(CLIENT, conf) : null;
+ connectionConf = getNewConnectionConf(useHttps, connTimeout, sslFactory);
}
@Override
public Client getHttpClient() {
ClientConfig config = new DefaultClientConfig(JSONRootElementProvider.App.class);
HttpURLConnectionFactory urlFactory = new PseudoAuthenticatedURLConnectionFactory(connectionConf);
- Client httpClient = new Client(new URLConnectionClientHandler(urlFactory), config);
- return httpClient;
+ return new Client(new URLConnectionClientHandler(urlFactory), config);
}
@VisibleForTesting
@@ -276,33 +281,38 @@ public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
URLEncoder.encode(UserGroupInformation.getCurrentUser().getShortUserName(), "UTF8");
HttpURLConnection httpURLConnection =
- (HttpURLConnection) (new URL(url.toString() + tokenString)).openConnection();
+ (HttpURLConnection) (new URL(url + tokenString)).openConnection();
this.connectionConf.configure(httpURLConnection);
return httpURLConnection;
}
}
+
+ @Override
+ public void close() {
+ if (sslFactory != null) {
+ sslFactory.destroy();
+ }
+ }
}
- private static ConnectionConfigurator getNewConnectionConf(final Configuration conf,
- final boolean useHttps,
- final int connTimeout) {
+ private static ConnectionConfigurator getNewConnectionConf(final boolean useHttps,
+ final int connTimeout,
+ final SSLFactory sslFactory) {
ConnectionConfigurator connectionConf = null;
if (useHttps) {
try {
- connectionConf = getNewSSLConnectionConf(conf, connTimeout);
+ connectionConf = getNewSSLConnectionConf(connTimeout, sslFactory);
} catch (IOException e) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Cannot load customized ssl related configuration."
- + " Falling back to system-generic settings.", e);
- }
+ LOG.debug("Cannot load customized ssl related configuration."
+ + " Falling back to system-generic settings.", e);
}
}
if (connectionConf == null) {
connectionConf = new ConnectionConfigurator() {
@Override
- public HttpURLConnection configure(HttpURLConnection httpURLConnection) throws IOException {
+ public HttpURLConnection configure(HttpURLConnection httpURLConnection) {
setTimeouts(httpURLConnection, connTimeout);
return httpURLConnection;
}
@@ -312,14 +322,12 @@ public HttpURLConnection configure(HttpURLConnection httpURLConnection) throws I
return connectionConf;
}
- private static ConnectionConfigurator getNewSSLConnectionConf(final Configuration conf,
- final int connTimeout)
+ private static ConnectionConfigurator getNewSSLConnectionConf(final int connTimeout,
+ final SSLFactory sslFactory)
throws IOException {
- final SSLFactory sslFactory;
final SSLSocketFactory sslSocketFactory;
final HostnameVerifier hostnameVerifier;
- sslFactory = new SSLFactory(CLIENT, conf);
try {
sslFactory.init();
sslSocketFactory = sslFactory.createSSLSocketFactory();
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/VertexStatus.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/VertexStatus.java
index dfb9bbe8cd..9efb12d612 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/VertexStatus.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/VertexStatus.java
@@ -59,6 +59,10 @@ public VertexStatus(VertexStatusProtoOrBuilder proxy) {
this.proxy = proxy;
}
+ public String getId() {
+ return proxy.getId();
+ }
+
public State getState() {
return getState(proxy.getState());
}
diff --git a/tez-api/src/main/java/org/apache/tez/dag/api/client/rpc/DAGClientRPCImpl.java b/tez-api/src/main/java/org/apache/tez/dag/api/client/rpc/DAGClientRPCImpl.java
index 02935dfd20..798160a4ab 100644
--- a/tez-api/src/main/java/org/apache/tez/dag/api/client/rpc/DAGClientRPCImpl.java
+++ b/tez-api/src/main/java/org/apache/tez/dag/api/client/rpc/DAGClientRPCImpl.java
@@ -23,6 +23,7 @@
import javax.annotation.Nullable;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
import org.apache.tez.common.RPCUtil;
import org.apache.tez.dag.api.SessionNotRunning;
@@ -47,6 +48,7 @@
import org.apache.tez.dag.api.client.VertexStatus;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetDAGStatusRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetVertexStatusRequestProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetWebUIAddressRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.TryKillDAGRequestProto;
import com.google.common.annotations.VisibleForTesting;
@@ -68,13 +70,16 @@ public class DAGClientRPCImpl extends DAGClientInternal {
@VisibleForTesting
DAGClientAMProtocolBlockingPB proxy = null;
+ private UserGroupInformation ugi;
+
public DAGClientRPCImpl(ApplicationId appId, String dagId,
- TezConfiguration conf, @Nullable FrameworkClient frameworkClient) {
+ TezConfiguration conf, @Nullable FrameworkClient frameworkClient, UserGroupInformation ugi) {
this.appId = appId;
this.dagId = dagId;
this.conf = conf;
this.frameworkClient = frameworkClient;
appReport = null;
+ this.ugi = ugi;
}
@Override
@@ -142,9 +147,7 @@ public String getSessionIdentifierString() {
@Override
public void tryKillDAG() throws TezException, IOException {
- if(LOG.isDebugEnabled()) {
- LOG.debug("TryKill for app: " + appId + " dag:" + dagId);
- }
+ LOG.debug("TryKill for app: {} dag:{}", appId, dagId);
try {
if (createAMProxyIfNeeded()) {
TryKillDAGRequestProto requestProto =
@@ -182,9 +185,7 @@ void resetProxy(Exception e) {
DAGStatus getDAGStatusViaAM(Set statusOptions, long timeout)
throws IOException, TezException {
- if(LOG.isDebugEnabled()) {
- LOG.debug("GetDAGStatus via AM for app: " + appId + " dag:" + dagId);
- }
+ LOG.debug("GetDAGStatus via AM for app: {} dag:{}", appId, dagId);
GetDAGStatusRequestProto.Builder requestProtoBuilder =
GetDAGStatusRequestProto.newBuilder()
.setDagId(dagId).setTimeout(timeout);
@@ -286,7 +287,7 @@ boolean createAMProxyIfNeeded() throws IOException, TezException,
}
proxy = TezClientUtils.getAMProxy(conf, appReport.getHost(), appReport.getRpcPort(),
- appReport.getClientToAMToken());
+ appReport.getClientToAMToken(), ugi);
return true;
}
@@ -303,4 +304,15 @@ public DAGStatus waitForCompletionWithStatusUpdates(@Nullable Set
throw new TezException("not supported");
}
+ @Override
+ public String getWebUIAddress() throws IOException, TezException {
+ LOG.debug("getWebUIAddress via AM for app: {} dag: {}", appId, dagId);
+ GetWebUIAddressRequestProto.Builder requestProtoBuilder = GetWebUIAddressRequestProto.newBuilder();
+ try {
+ return proxy.getWebUIAddress(null, requestProtoBuilder.build()).getWebUiAddress();
+ } catch (ServiceException e) {
+ RPCUtil.unwrapAndThrowException(e);
+ throw new TezException(e);
+ }
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/Input.java b/tez-api/src/main/java/org/apache/tez/runtime/api/Input.java
index bda439616e..a901d8aa7a 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/Input.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/Input.java
@@ -26,7 +26,7 @@
*
* This interface has methods which can be used by a {@link org.apache.tez.runtime.api.Processor}
* to control execution of this Input and read data from it.
- *
+ *
* Actual implementations are expected to derive from {@link AbstractLogicalInput}
*/
@Public
@@ -36,17 +36,17 @@ public interface Input {
/**
* Start any processing that the Input may need to perform. It is the
* responsibility of the Processor to start Inputs.
- *
+ *
* This typically acts as a signal to Inputs to start any Processing that they
- * may required. A blocking implementation of this method should not be used
+ * may require. A blocking implementation of this method should not be used
* as a mechanism to determine when an Input is actually ready.
- *
+ *
* This method may be invoked by the framework under certain circumstances,
* and as such requires the implementation to be non-blocking.
- *
+ *
* Inputs must be written to handle multiple start invocations - typically
* honoring only the first one.
- *
+ *
* @throws Exception
*/
public void start() throws Exception;
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/InputContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/InputContext.java
index 479a7dba1b..6eac2dfc95 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/InputContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/InputContext.java
@@ -32,6 +32,12 @@ public interface InputContext extends TaskContext {
* @return Name of the Source Vertex
*/
public String getSourceVertexName();
+
+ /**
+ * Returns a convenient, human-readable string describing the input and output vertices.
+ * @return the convenient string
+ */
+ String getInputOutputVertexNames();
/**
* Get the index of the input in the set of all inputs for the task. The
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/InputInitializerContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/InputInitializerContext.java
index 6a123cf1a1..5cb2d221b3 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/InputInitializerContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/InputInitializerContext.java
@@ -24,8 +24,10 @@
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.Resource;
+import org.apache.tez.common.counters.TezCounters;
import org.apache.tez.dag.api.UserPayload;
import org.apache.tez.dag.api.event.VertexState;
import org.apache.tez.dag.api.event.VertexStateUpdate;
@@ -48,7 +50,13 @@ public interface InputInitializerContext {
* @return DAG name
*/
String getDAGName();
-
+
+ /**
+ * Get vertex configuration
+ * @return Vertex configuration
+ */
+ Configuration getVertexConfiguration();
+
/**
* Get the name of the input
* @return Input name
@@ -79,7 +87,12 @@ public interface InputInitializerContext {
* @return Resource
*/
Resource getVertexTaskResource();
-
+
+ /**
+ * Get the vertex id as integer that belongs to this input.
+ */
+ int getVertexId();
+
/**
* Get the total resource allocated to this vertex. If the DAG is running in
* a busy cluster then it may have no resources available dedicated to it. The
@@ -117,4 +130,10 @@ public interface InputInitializerContext {
*/
void registerForVertexStateUpdates(String vertexName, @Nullable Set stateSet);
+ /**
+ * Add custom counters
+ *
+ * @param tezCounters counters to add
+ */
+ void addCounters(TezCounters tezCounters);
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/OutputCommitterContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/OutputCommitterContext.java
index d254a6a99e..5b8906d520 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/OutputCommitterContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/OutputCommitterContext.java
@@ -78,4 +78,6 @@ public interface OutputCommitterContext {
*/
public int getVertexIndex();
+ public int getDagIdentifier();
+
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/OutputContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/OutputContext.java
index 882eb4be2a..f0de897fda 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/OutputContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/OutputContext.java
@@ -19,6 +19,7 @@
package org.apache.tez.runtime.api;
import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.yarn.event.EventHandler;
/**
* Context handle for the Output to initialize itself.
@@ -32,20 +33,35 @@ public interface OutputContext extends TaskContext {
* Output's data
* @return Name of the Destination Vertex
*/
- public String getDestinationVertexName();
-
+ String getDestinationVertexName();
+
+ /**
+ * Returns a convenient, human-readable string describing the input and output vertices.
+ * @return the convenient string
+ */
+ String getInputOutputVertexNames();
+
/**
* Get the index of the output in the set of all outputs for the task. The
* index will be consistent and valid only among the tasks of this vertex.
* @return index
*/
- public int getOutputIndex();
+ int getOutputIndex();
/**
* Get an {@link OutputStatisticsReporter} for this {@link Output} that can
* be used to report statistics like data size
* @return {@link OutputStatisticsReporter}
*/
- public OutputStatisticsReporter getStatisticsReporter();
+ OutputStatisticsReporter getStatisticsReporter();
+
+ /**
+ * Notify the context that at this point no more events should be sent.
+ * This is used as a safety measure to prevent events being sent after close
+ * or in cleanup. After this is called events being queued to be sent to the
+ * AM will instead be passed to the event handler.
+ * @param eventHandler should handle the events after the call.
+ */
+ void trapEvents(EventHandler eventHandler);
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/ProcessorContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/ProcessorContext.java
index acb2a57da7..3782a8d8d7 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/ProcessorContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/ProcessorContext.java
@@ -22,6 +22,7 @@
import java.util.Collection;
import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.tez.common.ProgressHelper;
/**
* Context handle for the Processor to initialize itself.
@@ -30,13 +31,32 @@
@Public
public interface ProcessorContext extends TaskContext {
+ /**
+ * validate that progress is the valid range.
+ * @param progress
+ * @return the processed value of the progress that is guaranteed to be within
+ * the valid range.
+ */
+ static float preProcessProgress(float progress) {
+ return ProgressHelper.processProgress(progress);
+ }
+
/**
* Set the overall progress of this Task Attempt.
* This automatically results in invocation of {@link ProcessorContext#notifyProgress()}
* and so invoking that separately is not required.
* @param progress Progress in the range from [0.0 - 1.0f]
*/
- public void setProgress(float progress);
+ default void setProgress(float progress) {
+ setProgressInternally(preProcessProgress(progress));
+ }
+
+ /**
+ * The actual implementation of the taskAttempt progress.
+ * All implementations needs to override this method
+ * @param progress
+ */
+ void setProgressInternally(float progress);
/**
* Check whether this attempt can commit its output
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/TaskContext.java b/tez-api/src/main/java/org/apache/tez/runtime/api/TaskContext.java
index dd2951a382..004295ddad 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/TaskContext.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/TaskContext.java
@@ -27,6 +27,7 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.tez.common.counters.TezCounters;
import org.apache.tez.dag.api.UserPayload;
@@ -62,6 +63,12 @@ public interface TaskContext {
*/
public int getTaskAttemptNumber();
+ /**
+ * Get container configuration
+ * @return Container configuration
+ */
+ public Configuration getContainerConfiguration();
+
/**
* Get the name of the DAG
* @return the DAG name
@@ -73,9 +80,9 @@ public interface TaskContext {
* @return Vertex Name
*/
public String getTaskVertexName();
-
+
/**
- * Get the index of this task's vertex in the set of vertices in the DAG. This
+ * Get the index of this task's vertex in the set of vertices in the DAG. This
* is consistent and valid across all tasks/vertices in the same DAG.
* @return index
*/
@@ -112,24 +119,24 @@ public interface TaskContext {
/**
* Returns an identifier which is unique to the specific Input, Processor or
* Output
- *
+ *
* @return a unique identifier
*/
public String getUniqueIdentifier();
-
+
/**
- * Returns a shared {@link ObjectRegistry} to hold user objects in memory
- * between tasks.
+ * Returns a shared {@link ObjectRegistry} to hold user objects in memory
+ * between tasks.
* @return {@link ObjectRegistry}
*/
public ObjectRegistry getObjectRegistry();
-
+
/**
- * Notifies the framework that progress is being made by this component.
+ * Notifies the framework that progress is being made by this component.
* This is used to identify hung components that are not making progress.
* Must be called periodically until processing has completed for this component.
- * Care must be taken to call this when real progress has been made. Simply
- * calling this continuously from a thread without regard to real work may prevent
+ * Care must be taken to call this when real progress has been made. Simply
+ * calling this continuously from a thread without regard to real work may prevent
* identification of hung components and delay/stall job completion.
*/
public void notifyProgress();
@@ -191,34 +198,34 @@ public interface TaskContext {
*/
@Nullable
public ByteBuffer getServiceProviderMetaData(String serviceName);
-
+
/**
* Request a specific amount of memory during initialization
* (initialize(..*Context)) The requester is notified of allocation via the
* provided callback handler.
- *
+ *
* Currently, (post TEZ-668) the caller will be informed about the available
* memory after initialization (I/P/O initialize(...)), and before the
* start/run invocation. There will be no other invocations on the callback.
- *
+ *
* This method can be called only once by any component. Calling it multiple
* times from within the same component will result in an error.
- *
+ *
* Each Input / Output must request memory. For Inputs / Outputs which do not
* have a specific ask, a null callback handler can be specified with a
* request size of 0.
- *
+ *
* @param size
* request size in bytes.
* @param callbackHandler
* the callback handler to be invoked once memory is assigned
*/
public void requestInitialMemory(long size, MemoryUpdateCallback callbackHandler);
-
+
/**
* Gets the total memory available to all components of the running task. This
* values will always be constant, and does not factor in any allocations.
- *
+ *
* @return the total available memory for all components of the task
*/
public long getTotalMemoryAvailableToTask();
@@ -241,8 +248,8 @@ public interface TaskContext {
* might not be guaranteed. The service returned works with tez framework, currently it provides
* thread reuse across tasks.
* Note: This is an unstable api, and is not recommended to be used by external users. Please wait
- * until API and code is stablized by use in Tez processors, input and outputs.
- * @param parallelism The expected parallelism for for this ExecutorService.
+ * until API and code is stabilized by use in Tez processors, input and outputs.
+ * @param parallelism The expected parallelism for this ExecutorService.
* @param threadNameFormat The thread name format, format will be given one parameter, threadId.
* @return An ExecutorService instance.
*/
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/CustomProcessorEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/CustomProcessorEvent.java
new file mode 100644
index 0000000000..7d84a1d79d
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/CustomProcessorEvent.java
@@ -0,0 +1,65 @@
+/**
+ * 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.tez.runtime.api.events;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceAudience.Private;
+import org.apache.tez.runtime.api.Event;
+
+import java.nio.ByteBuffer;
+
+public class CustomProcessorEvent extends Event {
+ private ByteBuffer payload;
+
+ /**
+ * Version number to indicate what app attempt generated this Event
+ */
+ private int version;
+
+ private CustomProcessorEvent(ByteBuffer payload) {
+ this(payload, -1);
+ }
+
+ private CustomProcessorEvent(ByteBuffer payload, int version) {
+ this.payload = payload;
+ this.version = version;
+ }
+
+ public static CustomProcessorEvent create(ByteBuffer payload) {
+ return new CustomProcessorEvent(payload);
+ }
+
+ @Private
+ public static CustomProcessorEvent create(ByteBuffer payload, int version) {
+ return new CustomProcessorEvent(payload, version);
+ }
+
+ public ByteBuffer getPayload() {
+ return payload.asReadOnlyBuffer();
+ }
+
+ @Private
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputDataInformationEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputDataInformationEvent.java
index a62a34154f..8cf0616e6b 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputDataInformationEvent.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputDataInformationEvent.java
@@ -49,8 +49,8 @@ public final class InputDataInformationEvent extends Event {
private final int sourceIndex;
private int targetIndex; // TODO Likely to be multiple at a later point.
private final ByteBuffer userPayload;
+ private String serializedPath;
private final Object userPayloadObject;
-
private InputDataInformationEvent(int srcIndex, ByteBuffer userPayload) {
this.sourceIndex = srcIndex;
@@ -79,6 +79,12 @@ public static InputDataInformationEvent createWithObjectPayload(int srcIndex,
return new InputDataInformationEvent(srcIndex, userPayloadDeserialized, null);
}
+ public static InputDataInformationEvent createWithSerializedPath(int srcIndex, String serializedPath) {
+ InputDataInformationEvent event = new InputDataInformationEvent(srcIndex, null);
+ event.serializedPath = serializedPath;
+ return event;
+ }
+
public int getSourceIndex() {
return this.sourceIndex;
}
@@ -90,19 +96,29 @@ public int getTargetIndex() {
public void setTargetIndex(int target) {
this.targetIndex = target;
}
-
+
+ public String getSerializedPath() {
+ return serializedPath;
+ }
+
public ByteBuffer getUserPayload() {
return userPayload == null ? null : userPayload.asReadOnlyBuffer();
}
-
+
public Object getDeserializedUserPayload() {
return this.userPayloadObject;
}
- @Override
public String toString() {
- return "InputDataInformationEvent [sourceIndex=" + sourceIndex + ", targetIndex="
- + targetIndex + ", serializedUserPayloadExists=" + (userPayload != null)
- + ", deserializedUserPayloadExists=" + (userPayloadObject != null) + "]";
- }
+ StringBuilder sb = new StringBuilder();
+ sb.append("InputDataInformationEvent [sourceIndex=").append(sourceIndex)
+ .append(", targetIndex=").append(targetIndex)
+ .append(", serializedUserPayloadExists=").append(userPayload != null)
+ .append(", deserializedUserPayloadExists=").append(userPayloadObject != null);
+ if (serializedPath != null) {
+ sb.append(", serializedPath=").append(serializedPath);
+ }
+ sb.append("]");
+ return sb.toString();
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputInitializerEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputInitializerEvent.java
index 3037e619b5..21ad130c88 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputInitializerEvent.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputInitializerEvent.java
@@ -21,8 +21,7 @@
package org.apache.tez.runtime.api.events;
import java.nio.ByteBuffer;
-
-import com.google.common.base.Preconditions;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceAudience.Public;
@@ -53,8 +52,8 @@ public class InputInitializerEvent extends Event {
private InputInitializerEvent(String targetVertexName, String targetInputName,
ByteBuffer eventPayload) {
- Preconditions.checkNotNull(targetVertexName, "TargetVertexName cannot be null");
- Preconditions.checkNotNull(targetInputName, "TargetInputName cannot be null");
+ Objects.requireNonNull(targetVertexName, "TargetVertexName cannot be null");
+ Objects.requireNonNull(targetInputName, "TargetInputName cannot be null");
this.targetVertexName = targetVertexName;
this.targetInputName = targetInputName;
this.eventPayload = eventPayload;
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputReadErrorEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputReadErrorEvent.java
index 7d2e0d25a8..6c9f1fbe6b 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputReadErrorEvent.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputReadErrorEvent.java
@@ -21,6 +21,10 @@
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.tez.runtime.api.Event;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
/**
* Event generated by an Input to indicate error when trying to retrieve data.
* This is not necessarily a fatal event - it's an indication to the AM to retry
@@ -44,17 +48,63 @@ public final class InputReadErrorEvent extends Event {
*/
private final int version;
- private InputReadErrorEvent(String diagnostics, int index,
- int version) {
+ /**
+ * Number of failures.
+ */
+ private final int numFailures;
+
+ /**
+ * Whether this input read error is caused while fetching local file.
+ */
+ private final boolean isLocalFetch;
+
+ /**
+ * Whether this input read error is caused because the fetcher detected a fatal, unrecoverable,
+ * local file read issue from the shuffle handler.
+ */
+ private final boolean isDiskErrorAtSource;
+
+ /**
+ * The localhostName of the destination task attempt.
+ */
+ private final String destinationLocalhostName;
+
+ private InputReadErrorEvent(final String diagnostics, final int index, final int version,
+ final int numFailures, boolean isLocalFetch, boolean isDiskErrorAtSource, String destinationLocalhostName) {
super();
this.diagnostics = diagnostics;
this.index = index;
this.version = version;
+ this.numFailures = numFailures;
+ this.isLocalFetch = isLocalFetch;
+ this.isDiskErrorAtSource = isDiskErrorAtSource;
+ this.destinationLocalhostName = destinationLocalhostName;
+ }
+
+ /**
+ * Creates an InputReadErrorEvent from less parameters, supposed to be used from tests only.
+ * @param diagnostics
+ * @param index
+ * @param version
+ * @return InputReadErrorEvent instance
+ */
+ @VisibleForTesting
+ public static InputReadErrorEvent create(String diagnostics, int index, int version) {
+ return create(diagnostics, index, version, 1, false, false, null);
}
- public static InputReadErrorEvent create(String diagnostics, int index,
- int version) {
- return new InputReadErrorEvent(diagnostics, index, version);
+ public static InputReadErrorEvent create(String diagnostics, int index, int version, boolean isLocalFetch,
+ boolean isDiskErrorAtSource, String destinationLocalhostName) {
+ return create(diagnostics, index, version, 1, isLocalFetch, isDiskErrorAtSource, destinationLocalhostName);
+ }
+
+ /**
+ * Create an InputReadErrorEvent.
+ */
+ public static InputReadErrorEvent create(final String diagnostics, final int index, final int version,
+ final int numFailures, boolean isLocalFetch, boolean isDiskErrorAtSource, String destinationLocalhostName) {
+ return new InputReadErrorEvent(diagnostics, index, version, numFailures, isLocalFetch, isDiskErrorAtSource,
+ destinationLocalhostName);
}
public String getDiagnostics() {
@@ -69,4 +119,39 @@ public int getVersion() {
return version;
}
+ /**
+ * @return number of failures
+ */
+ public int getNumFailures() {
+ return numFailures;
+ }
+
+ public boolean isLocalFetch() {
+ return isLocalFetch;
+ }
+
+ public boolean isDiskErrorAtSource() {
+ return isDiskErrorAtSource;
+ }
+
+ public String getDestinationLocalhostName(){
+ return destinationLocalhostName;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(index, version);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ InputReadErrorEvent that = (InputReadErrorEvent) o;
+ return index == that.index && version == that.version;
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputUpdatePayloadEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputUpdatePayloadEvent.java
index 2cfec69589..8c336354d9 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputUpdatePayloadEvent.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/InputUpdatePayloadEvent.java
@@ -19,14 +19,13 @@
package org.apache.tez.runtime.api.events;
import java.nio.ByteBuffer;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.tez.runtime.api.Event;
import org.apache.tez.runtime.api.InputInitializer;
-import com.google.common.base.Preconditions;
-
/**
* Events used by {@link InputInitializer} implementations to update the
* shared user payload for the Input that is being initialized.
@@ -41,7 +40,7 @@ public class InputUpdatePayloadEvent extends Event {
private final ByteBuffer userPayload;
private InputUpdatePayloadEvent(ByteBuffer userPayload) {
- Preconditions.checkNotNull(userPayload);
+ Objects.requireNonNull(userPayload);
this.userPayload = userPayload;
}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/api/events/VertexManagerEvent.java b/tez-api/src/main/java/org/apache/tez/runtime/api/events/VertexManagerEvent.java
index 9e73fe5d00..7a450c6cdf 100644
--- a/tez-api/src/main/java/org/apache/tez/runtime/api/events/VertexManagerEvent.java
+++ b/tez-api/src/main/java/org/apache/tez/runtime/api/events/VertexManagerEvent.java
@@ -19,6 +19,7 @@
package org.apache.tez.runtime.api.events;
import java.nio.ByteBuffer;
+import java.util.Objects;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceAudience.Public;
@@ -27,8 +28,6 @@
import org.apache.tez.runtime.api.Event;
import org.apache.tez.runtime.api.TaskAttemptIdentifier;
-import com.google.common.base.Preconditions;
-
/**
* Event used to send information from a Task to the VertexManager for a vertex.
* This may be used to send statistics like samples etc to the VertexManager for
@@ -50,11 +49,17 @@ public class VertexManagerEvent extends Event {
*/
private final ByteBuffer userPayload;
+ /**
+ * Constructor.
+ *
+ * @param vertexName
+ * @param userPayload
+ * @throws NullPointerException if {@code vertexName} or {@code userPayload}
+ * is {@code null}
+ */
private VertexManagerEvent(String vertexName, ByteBuffer userPayload) {
- Preconditions.checkArgument(vertexName != null);
- Preconditions.checkArgument(userPayload != null);
- this.targetVertexName = vertexName;
- this.userPayload = userPayload;
+ this.targetVertexName = Objects.requireNonNull(vertexName);
+ this.userPayload = Objects.requireNonNull(userPayload);
}
/**
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/ShuffleHandlerError.java b/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/ShuffleHandlerError.java
new file mode 100644
index 0000000000..09137de673
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/ShuffleHandlerError.java
@@ -0,0 +1,27 @@
+/**
+* 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.tez.runtime.library.common.shuffle.api;
+
+/**
+ * ShuffleHandlerError enum encapsulates possible error messages that can be propagated from
+ * ShuffleHandler to fetchers. Depending on the message, fetchers can make better decisions, or give
+ * AM a hint in order to let it make better decisions in case of shuffle issues.
+ */
+public enum ShuffleHandlerError {
+ DISK_ERROR_EXCEPTION
+}
diff --git a/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/package-info.java b/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/package-info.java
new file mode 100644
index 0000000000..9ad8e61d50
--- /dev/null
+++ b/tez-api/src/main/java/org/apache/tez/runtime/library/common/shuffle/api/package-info.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+
+@Private
+package org.apache.tez.runtime.library.common.shuffle.api;
+
+import org.apache.hadoop.classification.InterfaceAudience.Private;
\ No newline at end of file
diff --git a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ContainerLauncherContext.java b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ContainerLauncherContext.java
index ed1d58f78a..16d54f05b7 100644
--- a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ContainerLauncherContext.java
+++ b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ContainerLauncherContext.java
@@ -80,7 +80,7 @@ void containerCompleted(ContainerId containerId, int exitStatus, String diagnost
* Get the number of nodes being handled by the specified source
*
* @param sourceName the relevant source name
- * @return the initial payload
+ * @return the number of nodes
*/
int getNumNodes(String sourceName);
diff --git a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/DagInfo.java b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/DagInfo.java
index 4a8b9fa8ce..b05fa8bbb7 100644
--- a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/DagInfo.java
+++ b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/DagInfo.java
@@ -14,8 +14,11 @@
package org.apache.tez.serviceplugins.api;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.Credentials;
+import java.util.BitSet;
+
public interface DagInfo {
/**
@@ -35,4 +38,10 @@ public interface DagInfo {
* @return the credentials for the dag.
*/
Credentials getCredentials();
+
+ int getTotalVertices();
+
+ BitSet getVertexDescendants(int vertexIndex);
+
+ Configuration getConf();
}
diff --git a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ServicePluginsDescriptor.java b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ServicePluginsDescriptor.java
index 39d2cb8102..c942a3ad3a 100644
--- a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ServicePluginsDescriptor.java
+++ b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/ServicePluginsDescriptor.java
@@ -16,7 +16,7 @@
import java.util.Arrays;
-import com.google.common.base.Preconditions;
+import org.apache.tez.common.Preconditions;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.tez.dag.api.TezConfiguration;
diff --git a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskScheduler.java b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskScheduler.java
index b28a684de5..42ff56f2ba 100644
--- a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskScheduler.java
+++ b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskScheduler.java
@@ -14,6 +14,8 @@
package org.apache.tez.serviceplugins.api;
+import java.util.List;
+
import javax.annotation.Nullable;
import org.apache.hadoop.classification.InterfaceAudience;
@@ -263,4 +265,19 @@ public abstract boolean deallocateTask(Object task, boolean taskSucceeded,
*/
public abstract void dagComplete() throws ServicePluginException;
+ /**
+ * Get the number of held containers.
+ */
+ public int getHeldContainersCount() {
+ return 0;
+ }
+
+ /**
+ * Callback to be used in the event of a container allocation.
+ */
+ protected void onContainersAllocated(List containers) {
+ for (Container container : containers) {
+ getContext().containerAllocated(container);
+ }
+ }
}
diff --git a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskSchedulerContext.java b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskSchedulerContext.java
index 97fe7ae834..74342e2807 100644
--- a/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskSchedulerContext.java
+++ b/tez-api/src/main/java/org/apache/tez/serviceplugins/api/TaskSchedulerContext.java
@@ -84,6 +84,20 @@ void taskAllocated(Object task,
Object appCookie,
Container container);
+ /**
+ * Indicate to the framework that a container is being allocated.
+ *
+ * @param container the actual container
+ */
+ void containerAllocated(Container container);
+
+ /**
+ * Indicate to the framework that a container is being reused:
+ * there is a task assigned to an already used container.
+ *
+ * @param container the actual container
+ */
+ void containerReused(Container container);
/**
* Indicate to the framework that a container has completed. This is typically used by sources
@@ -220,4 +234,5 @@ void setApplicationRegistrationData(
*/
AMState getAMState();
+ int getVertexIndexForTask(Object task);
}
diff --git a/tez-api/src/main/javadoc/resources/META-INF/LICENSE.txt b/tez-api/src/main/javadoc/resources/META-INF/LICENSE
similarity index 100%
rename from tez-api/src/main/javadoc/resources/META-INF/LICENSE.txt
rename to tez-api/src/main/javadoc/resources/META-INF/LICENSE
diff --git a/tez-api/src/main/resources/META-INF/NOTICE.txt b/tez-api/src/main/javadoc/resources/META-INF/NOTICE
similarity index 69%
rename from tez-api/src/main/resources/META-INF/NOTICE.txt
rename to tez-api/src/main/javadoc/resources/META-INF/NOTICE
index 3f36fcc6ba..2595905699 100644
--- a/tez-api/src/main/resources/META-INF/NOTICE.txt
+++ b/tez-api/src/main/javadoc/resources/META-INF/NOTICE
@@ -1,5 +1,5 @@
Apache Tez
-Copyright (c) 2016 The Apache Software Foundation
+Copyright 2014-2024 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/tez-api/src/main/proto/DAGApiRecords.proto b/tez-api/src/main/proto/DAGApiRecords.proto
index c84094b51e..15f681db96 100644
--- a/tez-api/src/main/proto/DAGApiRecords.proto
+++ b/tez-api/src/main/proto/DAGApiRecords.proto
@@ -227,6 +227,7 @@ message ProgressProto {
optional int32 killedTaskCount = 5;
optional int32 failedTaskAttemptCount = 6;
optional int32 killedTaskAttemptCount = 7;
+ optional int32 rejectedTaskAttemptCount = 8;
}
enum VertexStatusStateProto {
@@ -244,10 +245,11 @@ enum VertexStatusStateProto {
}
message VertexStatusProto {
- optional VertexStatusStateProto state = 1;
- repeated string diagnostics = 2;
- optional ProgressProto progress = 3;
- optional TezCountersProto vertexCounters = 4;
+ required string id = 1;
+ optional VertexStatusStateProto state = 2;
+ repeated string diagnostics = 3;
+ optional ProgressProto progress = 4;
+ optional TezCountersProto vertexCounters = 5;
}
enum DAGStatusStateProto {
@@ -273,6 +275,8 @@ message DAGStatusProto {
optional ProgressProto DAGProgress = 3;
repeated StringProgressPairProto vertexProgress = 4;
optional TezCountersProto dagCounters = 5;
+ optional int64 memoryUsedByAM = 6;
+ optional int64 memoryUsedByTasks = 7;
}
message PlanLocalResourcesProto {
@@ -297,6 +301,7 @@ message TezCountersProto {
enum StatusGetOptsProto {
GET_COUNTERS = 0;
+ GET_MEMORY_USAGE = 1;
}
message VertexLocationHintProto {
diff --git a/tez-api/src/main/proto/DAGClientAMProtocol.proto b/tez-api/src/main/proto/DAGClientAMProtocol.proto
index 113c9ccfce..f0ff3916ea 100644
--- a/tez-api/src/main/proto/DAGClientAMProtocol.proto
+++ b/tez-api/src/main/proto/DAGClientAMProtocol.proto
@@ -90,6 +90,13 @@ message GetAMStatusResponseProto {
required TezAppMasterStatusProto status = 1;
}
+message GetWebUIAddressRequestProto {
+}
+
+message GetWebUIAddressResponseProto {
+ required string web_ui_address = 1;
+}
+
service DAGClientAMProtocol {
rpc getAllDAGs (GetAllDAGsRequestProto) returns (GetAllDAGsResponseProto);
rpc getDAGStatus (GetDAGStatusRequestProto) returns (GetDAGStatusResponseProto);
@@ -98,4 +105,5 @@ service DAGClientAMProtocol {
rpc submitDAG (SubmitDAGRequestProto) returns (SubmitDAGResponseProto);
rpc shutdownSession (ShutdownSessionRequestProto) returns (ShutdownSessionResponseProto);
rpc getAMStatus (GetAMStatusRequestProto) returns (GetAMStatusResponseProto);
+ rpc getWebUIAddress (GetWebUIAddressRequestProto) returns (GetWebUIAddressResponseProto);
}
diff --git a/tez-api/src/main/proto/Events.proto b/tez-api/src/main/proto/Events.proto
index e018864939..05896ac62e 100644
--- a/tez-api/src/main/proto/Events.proto
+++ b/tez-api/src/main/proto/Events.proto
@@ -39,6 +39,9 @@ message InputReadErrorEventProto {
optional int32 index = 1;
optional string diagnostics = 2;
optional int32 version = 3;
+ optional bool is_local_fetch = 4;
+ optional bool is_disk_error_at_source = 5;
+ optional string destination_localhost_name = 6;
}
message InputFailedEventProto {
@@ -55,6 +58,7 @@ message RootInputDataInformationEventProto {
optional int32 source_index = 1;
optional int32 target_index = 2;
optional bytes user_payload = 3;
+ optional bytes serialized_path = 4;
}
message CompositeEventProto {
@@ -69,3 +73,8 @@ message RootInputInitializerEventProto {
optional string target_input_name = 2;
optional bytes user_payload = 3;
}
+
+message CustomProcessorEventProto {
+ optional bytes user_payload = 1;
+ required int32 version = 2;
+}
diff --git a/tez-api/src/main/resources/META-INF/LICENSE.txt b/tez-api/src/main/resources/META-INF/LICENSE
similarity index 100%
rename from tez-api/src/main/resources/META-INF/LICENSE.txt
rename to tez-api/src/main/resources/META-INF/LICENSE
diff --git a/NOTICE.txt b/tez-api/src/main/resources/META-INF/NOTICE
similarity index 69%
rename from NOTICE.txt
rename to tez-api/src/main/resources/META-INF/NOTICE
index 3f36fcc6ba..2595905699 100644
--- a/NOTICE.txt
+++ b/tez-api/src/main/resources/META-INF/NOTICE
@@ -1,5 +1,5 @@
Apache Tez
-Copyright (c) 2016 The Apache Software Foundation
+Copyright 2014-2024 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/tez-api/src/main/resources/tez-api-version-info.properties b/tez-api/src/main/resources/tez-api-version-info.properties
index 4bb7d40b8b..0bc30c4bb0 100644
--- a/tez-api/src/main/resources/tez-api-version-info.properties
+++ b/tez-api/src/main/resources/tez-api-version-info.properties
@@ -19,4 +19,6 @@
version=${pom.version}
revision=${buildNumber}
buildtime=${build.time}
+builduser=${user.name}
+buildjavaversion=${java.version}
scmurl=${scm.url}
diff --git a/tez-api/src/test/java/org/apache/tez/client/TestTezClient.java b/tez-api/src/test/java/org/apache/tez/client/TestTezClient.java
index 89310df83e..1b93f924a2 100644
--- a/tez-api/src/test/java/org/apache/tez/client/TestTezClient.java
+++ b/tez-api/src/test/java/org/apache/tez/client/TestTezClient.java
@@ -18,6 +18,7 @@
package org.apache.tez.client;
+import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
@@ -37,13 +38,14 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -54,6 +56,7 @@
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.Credentials;
+import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
@@ -65,7 +68,6 @@
import org.apache.hadoop.yarn.api.records.URL;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.client.api.YarnClient;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.tez.common.counters.LimitExceededException;
@@ -87,9 +89,12 @@
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolBlockingPB;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetAMStatusResponseProto;
-import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.ShutdownSessionRequestProto;
+import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetDAGStatusResponseProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.SubmitDAGRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.TezAppMasterStatusProto;
+import org.apache.tez.dag.api.records.DAGProtos.DAGStatusProto;
+import org.apache.tez.dag.api.records.DAGProtos.DAGStatusStateProto;
+import org.apache.tez.dag.api.records.DAGProtos.ProgressProto;
import org.apache.tez.serviceplugins.api.ServicePluginsDescriptor;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
@@ -101,35 +106,73 @@
public class TestTezClient {
static final long HARD_KILL_TIMEOUT = 1500L;
+ private static final File STAGING_DIR = new File(System.getProperty("test.build.data"),
+ TestTezClient.class.getName()).getAbsoluteFile();
class TezClientForTest extends TezClient {
- TezYarnClient mockTezYarnClient;
DAGClientAMProtocolBlockingPB sessionAmProxy;
YarnClient mockYarnClient;
ApplicationId mockAppId;
boolean callRealGetSessionAMProxy;
+ Long prewarmTimeoutMs;
public TezClientForTest(String name, TezConfiguration tezConf,
- @Nullable Map localResources,
- @Nullable Credentials credentials) {
+ @Nullable Map localResources, @Nullable Credentials credentials) {
super(name, tezConf, localResources, credentials);
}
-
+
@Override
protected FrameworkClient createFrameworkClient() {
- return mockTezYarnClient;
+ return frameworkClient; // already initialized
}
-
+
+ public void setPrewarmTimeoutMs(Long prewarmTimeoutMs) {
+ this.prewarmTimeoutMs = prewarmTimeoutMs;
+ }
+
@Override
- protected DAGClientAMProtocolBlockingPB getAMProxy(ApplicationId appId)
- throws TezException, IOException {
- if (!callRealGetSessionAMProxy) {
- return sessionAmProxy;
+ protected long getPrewarmWaitTimeMs() {
+ return prewarmTimeoutMs == null ? super.getPrewarmWaitTimeMs() : prewarmTimeoutMs;
+ }
+ }
+
+ class TezYarnClientForTest extends TezYarnClient {
+ private TezClientForTest client;
+
+ protected TezYarnClientForTest(YarnClient yarnClient, TezClientForTest client) {
+ super(yarnClient);
+ this.client = client;
+ }
+
+ @Override
+ protected DAGClientAMProtocolBlockingPB waitForProxy(long clientTimeout, Configuration conf,
+ ApplicationId sessionAppId, UserGroupInformation ugi) throws TezException, IOException {
+ if (!client.callRealGetSessionAMProxy) {
+ return client.sessionAmProxy;
+ }
+ return super.getProxy(conf, sessionAppId, ugi);
+ }
+
+ @Override
+ protected DAGClientAMProtocolBlockingPB getProxy(Configuration conf, ApplicationId sessionAppId,
+ UserGroupInformation ugi) throws TezException, IOException {
+ if (!client.callRealGetSessionAMProxy) {
+ return client.sessionAmProxy;
}
- return super.getAMProxy(appId);
+ return super.getProxy(conf, sessionAppId, ugi);
+ }
+
+ @Override
+ public String getAmHost() {
+ return "testhost";
+ }
+
+ @Override
+ public int getAmPort() {
+ return 1234;
}
}
-
+
TezClientForTest configureAndCreateTezClient() throws YarnException, IOException, ServiceException {
return configureAndCreateTezClient(null);
}
@@ -146,34 +189,36 @@ TezClientForTest configureAndCreateTezClient(Map lrs, boo
}
conf.setBoolean(TezConfiguration.TEZ_IGNORE_LIB_URIS, true);
conf.setBoolean(TezConfiguration.TEZ_AM_SESSION_MODE, isSession);
+ conf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGING_DIR.getAbsolutePath());
TezClientForTest client = new TezClientForTest("test", conf, lrs, null);
ApplicationId appId1 = ApplicationId.newInstance(0, 1);
YarnClient yarnClient = mock(YarnClient.class, RETURNS_DEEP_STUBS);
when(yarnClient.createApplication().getNewApplicationResponse().getApplicationId()).thenReturn(appId1);
when(yarnClient.getApplicationReport(appId1).getYarnApplicationState()).thenReturn(YarnApplicationState.NEW);
- when(yarnClient.submitApplication(any(ApplicationSubmissionContext.class))).thenReturn(appId1);
+ when(yarnClient.submitApplication(any())).thenReturn(appId1);
DAGClientAMProtocolBlockingPB sessionAmProxy = mock(DAGClientAMProtocolBlockingPB.class, RETURNS_DEEP_STUBS);
- when(sessionAmProxy.getAMStatus(any(RpcController.class), any(GetAMStatusRequestProto.class)))
+ when(sessionAmProxy.getAMStatus(any(), any()))
+ .thenReturn(GetAMStatusResponseProto.newBuilder().setStatus(TezAppMasterStatusProto.RUNNING).build())
.thenReturn(GetAMStatusResponseProto.newBuilder().setStatus(TezAppMasterStatusProto.RUNNING).build());
client.sessionAmProxy = sessionAmProxy;
- client.mockTezYarnClient = new TezYarnClient(yarnClient);
+ client.frameworkClient = new TezYarnClientForTest(yarnClient, client);
client.mockYarnClient = yarnClient;
client.mockAppId = appId1;
-
- return client;
+
+ return client;
}
@Test (timeout = 5000)
- public void testTezclientApp() throws Exception {
- testTezClient(false);
+ public void testTezClientApp() throws Exception {
+ testTezClient(false, true, "testTezClientApp");
}
@Test (timeout = 5000)
- public void testTezclientSession() throws Exception {
- testTezClient(true);
+ public void testTezClientSession() throws Exception {
+ testTezClient(true, true, "testTezClientSession");
}
@Test (timeout = 5000)
@@ -211,7 +256,7 @@ private void _testTezClientSessionLargeDAGPlan(int maxIPCMsgSize, int payloadSiz
ProcessorDescriptor processorDescriptor = ProcessorDescriptor.create("P");
processorDescriptor.setUserPayload(UserPayload.create(ByteBuffer.allocate(payloadSize)));
Vertex vertex = Vertex.create("Vertex", processorDescriptor, 1, Resource.newInstance(1, 1));
- DAG dag = DAG.create("DAG").addVertex(vertex);
+ DAG dag = DAG.create("DAG-testTezClientSessionLargeDAGPlan").addVertex(vertex);
client.start();
client.addAppMasterLocalFiles(localResourceMap);
@@ -219,7 +264,7 @@ private void _testTezClientSessionLargeDAGPlan(int maxIPCMsgSize, int payloadSiz
client.stop();
ArgumentCaptor captor = ArgumentCaptor.forClass(SubmitDAGRequestProto.class);
- verify(client.sessionAmProxy).submitDAG((RpcController)any(), captor.capture());
+ verify(client.sessionAmProxy).submitDAG(any(), captor.capture());
SubmitDAGRequestProto request = captor.getValue();
if (shouldSerialize) {
@@ -238,8 +283,51 @@ private void _testTezClientSessionLargeDAGPlan(int maxIPCMsgSize, int payloadSiz
assertTrue(request.hasAdditionalAmResources());
}
}
+
+ @Test (timeout = 5000)
+ public void testGetClient() throws Exception {
+ /* BEGIN first TezClient usage without calling stop() */
+ TezClientForTest client = testTezClient(true, false, "testGetClient");
+ /* END first TezClient usage without calling stop() */
+
+ /* BEGIN reuse of AM from new TezClient */
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ApplicationSubmissionContext.class);
+ when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
+ .thenReturn(YarnApplicationState.RUNNING);
+
+ //Reuse existing appId from first TezClient
+ ApplicationId existingAppId = client.mockAppId;
+ TezClientForTest client2 = configureAndCreateTezClient(null, true,
+ client.amConfig.getTezConfiguration());
+ String mockLR1Name = "LR1";
+ Map lrDAG = Collections.singletonMap(mockLR1Name, LocalResource
+ .newInstance(URL.newInstance("file", "localhost", 0, "/test1"), LocalResourceType.FILE,
+ LocalResourceVisibility.PUBLIC, 1, 1));
+ Vertex vertex = Vertex.create("Vertex", ProcessorDescriptor.create("P"), 1,
+ Resource.newInstance(1, 1));
+ DAG dag = DAG.create("DAG-testGetClient").addVertex(vertex).addTaskLocalFiles(lrDAG);
+
+ //Bind TezClient to existing app and submit a dag
+ DAGClient dagClient = client2.getClient(existingAppId).submitDAG(dag);
+
+ assertTrue(dagClient.getExecutionContext().contains(existingAppId.toString()));
+ assertEquals(dagClient.getSessionIdentifierString(), existingAppId.toString());
+
+ // Validate request for new AM is not submitted to RM */
+ verify(client2.mockYarnClient, times(0)).submitApplication(captor.capture());
+
+ // Validate dag submission from second TezClient as normal */
+ verify(client2.sessionAmProxy, times(1)).submitDAG(any(), any());
+
+ // Validate stop from new TezClient as normal */
+ client2.stop();
+ verify(client2.sessionAmProxy, times(1)).shutdownSession(any(),
+ any());
+ verify(client2.mockYarnClient, times(1)).stop();
+ /* END reuse of AM from new TezClient */
+ }
- public void testTezClient(boolean isSession) throws Exception {
+ public TezClientForTest testTezClient(boolean isSession, boolean shouldStop, String dagName) throws Exception {
Map lrs = Maps.newHashMap();
String lrName1 = "LR1";
lrs.put(lrName1, LocalResource.newInstance(URL.newInstance("file", "localhost", 0, "/test"),
@@ -251,7 +339,7 @@ public void testTezClient(boolean isSession) throws Exception {
when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
.thenReturn(YarnApplicationState.RUNNING);
client.start();
- verify(client.mockYarnClient, times(1)).init((Configuration)any());
+ verify(client.mockYarnClient, times(1)).init(any());
verify(client.mockYarnClient, times(1)).start();
if (isSession) {
verify(client.mockYarnClient, times(1)).submitApplication(captor.capture());
@@ -273,7 +361,11 @@ public void testTezClient(boolean isSession) throws Exception {
LocalResourceVisibility.PUBLIC, 1, 1));
Vertex vertex = Vertex.create("Vertex", ProcessorDescriptor.create("P"), 1,
Resource.newInstance(1, 1));
- DAG dag = DAG.create("DAG").addVertex(vertex).addTaskLocalFiles(lrDAG);
+ DAG dag = DAG.create("DAG-" + dagName).addVertex(vertex).addTaskLocalFiles(lrDAG);
+ if (!isSession) {
+ when(client.sessionAmProxy.getAMStatus(any(), any()))
+ .thenReturn(GetAMStatusResponseProto.newBuilder().setStatus(TezAppMasterStatusProto.SHUTDOWN).build());
+ }
DAGClient dagClient = client.submitDAG(dag);
assertTrue(dagClient.getExecutionContext().contains(client.mockAppId.toString()));
@@ -281,7 +373,7 @@ public void testTezClient(boolean isSession) throws Exception {
if (isSession) {
verify(client.mockYarnClient, times(1)).submitApplication(captor.capture());
- verify(client.sessionAmProxy, times(1)).submitDAG((RpcController)any(), (SubmitDAGRequestProto) any());
+ verify(client.sessionAmProxy, times(1)).submitDAG(any(), any());
} else {
verify(client.mockYarnClient, times(1)).submitApplication(captor.capture());
ApplicationSubmissionContext context = captor.getValue();
@@ -309,7 +401,7 @@ public void testTezClient(boolean isSession) throws Exception {
when(client.mockYarnClient.getApplicationReport(appId2).getYarnApplicationState())
.thenReturn(YarnApplicationState.RUNNING);
- dag = DAG.create("DAG").addVertex(
+ dag = DAG.create("DAG-2-" + dagName).addVertex(
Vertex.create("Vertex", ProcessorDescriptor.create("P"), 1, Resource.newInstance(1, 1)));
dagClient = client.submitDAG(dag);
@@ -320,7 +412,7 @@ public void testTezClient(boolean isSession) throws Exception {
assertEquals(dagClient.getSessionIdentifierString(), client.mockAppId.toString());
// additional resource is sent
ArgumentCaptor captor1 = ArgumentCaptor.forClass(SubmitDAGRequestProto.class);
- verify(client.sessionAmProxy, times(2)).submitDAG((RpcController)any(), captor1.capture());
+ verify(client.sessionAmProxy, times(2)).submitDAG(any(), captor1.capture());
SubmitDAGRequestProto proto = captor1.getValue();
Assert.assertEquals(1, proto.getAdditionalAmResources().getLocalResourcesCount());
Assert.assertEquals(lrName2, proto.getAdditionalAmResources().getLocalResources(0).getName());
@@ -343,13 +435,16 @@ public void testTezClient(boolean isSession) throws Exception {
assertTrue(context.getAMContainerSpec().getLocalResources().containsKey(
lrName2));
}
-
- client.stop();
- if (isSession) {
- verify(client.sessionAmProxy, times(1)).shutdownSession((RpcController) any(),
- (ShutdownSessionRequestProto) any());
+
+ if(shouldStop) {
+ client.stop();
+ if (isSession) {
+ verify(client.sessionAmProxy, times(1)).shutdownSession(any(),
+ any());
+ }
+ verify(client.mockYarnClient, times(1)).stop();
}
- verify(client.mockYarnClient, times(1)).stop();
+ return client;
}
@Test (timeout=5000)
@@ -358,23 +453,54 @@ public void testPreWarm() throws Exception {
client.start();
when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
- .thenReturn(YarnApplicationState.RUNNING);
+ .thenReturn(YarnApplicationState.RUNNING);
when(
- client.sessionAmProxy.getAMStatus((RpcController) any(), (GetAMStatusRequestProto) any()))
+ client.sessionAmProxy.getAMStatus(any(), any()))
.thenReturn(GetAMStatusResponseProto.newBuilder().setStatus(TezAppMasterStatusProto.READY).build());
PreWarmVertex vertex = PreWarmVertex.create("PreWarm", 1, Resource.newInstance(1, 1));
client.preWarm(vertex);
ArgumentCaptor captor1 = ArgumentCaptor.forClass(SubmitDAGRequestProto.class);
- verify(client.sessionAmProxy, times(1)).submitDAG((RpcController)any(), captor1.capture());
+ verify(client.sessionAmProxy, times(1)).submitDAG(any(), captor1.capture());
SubmitDAGRequestProto proto = captor1.getValue();
assertTrue(proto.getDAGPlan().getName().startsWith(TezConstants.TEZ_PREWARM_DAG_NAME_PREFIX));
+ setClientToReportStoppedDags(client);
+ client.stop();
+ }
+
+
+ @Test (timeout=5000)
+ public void testPreWarmCloseStuck() throws Exception {
+ TezClientForTest client = configureAndCreateTezClient();
+ client.setPrewarmTimeoutMs(10L); // Don't wait too long.
+ client.start();
+
+ when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
+ .thenReturn(YarnApplicationState.RUNNING);
+ when(client.sessionAmProxy.getAMStatus(any(), any()))
+ .thenReturn(GetAMStatusResponseProto.newBuilder().setStatus(TezAppMasterStatusProto.READY).build());
+
+ PreWarmVertex vertex = PreWarmVertex.create("PreWarm", 1, Resource.newInstance(1, 1));
+ client.preWarm(vertex);
+ // Keep prewarm in "running" state. Client should give up waiting; if it doesn't, the test will time out.
client.stop();
}
+
+ private void setClientToReportStoppedDags(TezClientForTest client) throws Exception {
+ when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
+ .thenReturn(YarnApplicationState.FINISHED);
+ when(client.sessionAmProxy.getDAGStatus(isNull(), any()))
+ .thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(DAGStatusProto.newBuilder()
+ .addDiagnostics("Diagnostics_0").setState(DAGStatusStateProto.DAG_SUCCEEDED)
+ .setDAGProgress(ProgressProto.newBuilder()
+ .setFailedTaskCount(0).setKilledTaskCount(0).setRunningTaskCount(0)
+ .setSucceededTaskCount(1).setTotalTaskCount(1).build()).build()).build());
+ }
+
@Test (timeout=30000)
public void testPreWarmWithTimeout() throws Exception {
long startTime = 0 , endTime = 0;
@@ -389,8 +515,8 @@ public void testPreWarmWithTimeout() throws Exception {
spyClient.mockAppId).getYarnApplicationState())
.thenReturn(YarnApplicationState.RUNNING);
when(
- spyClient.sessionAmProxy.getAMStatus((RpcController) any(),
- (GetAMStatusRequestProto) any()))
+ spyClient.sessionAmProxy.getAMStatus(any(),
+ any()))
.thenReturn(
GetAMStatusResponseProto.newBuilder().setStatus(
TezAppMasterStatusProto.INITIALIZING).build());
@@ -405,15 +531,15 @@ public void testPreWarmWithTimeout() throws Exception {
endTime = Time.monotonicNow();
assertTrue("Time taken is not as expected",
(endTime - startTime) > timeout);
- verify(spyClient, times(0)).submitDAG(any(DAG.class));
- Assert.assertTrue("Unexpected Exception message",
+ verify(spyClient, times(0)).submitDAG(any());
+ Assert.assertTrue("Unexpected Exception message: " + te.getMessage(),
te.getMessage().contains("Tez AM not ready"));
}
when(
- spyClient.sessionAmProxy.getAMStatus((RpcController) any(),
- (GetAMStatusRequestProto) any()))
+ spyClient.sessionAmProxy.getAMStatus(any(),
+ any()))
.thenReturn(
GetAMStatusResponseProto.newBuilder().setStatus(
TezAppMasterStatusProto.READY).build());
@@ -423,7 +549,7 @@ public void testPreWarmWithTimeout() throws Exception {
endTime = Time.monotonicNow();
assertTrue("Time taken is not as expected",
(endTime - startTime) <= timeout);
- verify(spyClient, times(1)).submitDAG(any(DAG.class));
+ verify(spyClient, times(1)).submitDAG(any());
} catch (TezException te) {
fail("PreWarm should have succeeded!");
}
@@ -458,7 +584,8 @@ public void run() {
endTime = Time.monotonicNow();
assertTrue("Time taken is not as expected",
(endTime - startTime) <= timeout);
- verify(spyClient, times(2)).submitDAG(any(DAG.class));
+ verify(spyClient, times(2)).submitDAG(any());
+ setClientToReportStoppedDags(client);
spyClient.stop();
client.stop();
}
@@ -486,7 +613,8 @@ public void testMultipleSubmissionsJob(boolean isSession) throws Exception {
LocalResourceVisibility.PUBLIC, 1, 1));
Vertex vertex = Vertex.create("Vertex", ProcessorDescriptor.create("P"), 1,
Resource.newInstance(1, 1)).addTaskLocalFiles(lrVertex);
- DAG dag = DAG.create("DAG").addVertex(vertex).addTaskLocalFiles(lrDAG);
+ DAG dag =
+ DAG.create("DAG-testMultipleSubmissionsJob-session-" + isSession).addVertex(vertex).addTaskLocalFiles(lrDAG);
// the dag resource will be added to the vertex once
client1.submitDAG(dag);
@@ -577,7 +705,7 @@ public void testSubmitDAGAppFailed() throws Exception {
Vertex vertex = Vertex.create("Vertex", ProcessorDescriptor.create("P"), 1,
Resource.newInstance(1, 1));
- DAG dag = DAG.create("DAG").addVertex(vertex);
+ DAG dag = DAG.create("DAG-testSubmitDAGAppFailed").addVertex(vertex);
try {
client.submitDAG(dag);
@@ -767,7 +895,7 @@ public void testClientResubmit() throws Exception {
Vertex vertex2 = Vertex.create("Vertex2", ProcessorDescriptor.create("P2"), 1,
Resource.newInstance(1, 1));
vertex2.setTaskLaunchCmdOpts("-XX:+UseParallelGC -XX:+UseG1GC");
- DAG dag = DAG.create("DAG").addVertex(vertex1).addVertex(vertex2).addTaskLocalFiles(lrDAG);
+ DAG dag = DAG.create("DAG-testClientResubmit").addVertex(vertex1).addVertex(vertex2).addTaskLocalFiles(lrDAG);
for (int i = 0; i < 3; ++i) {
try {
client.submitDAG(dag);
@@ -790,7 +918,7 @@ public void testMissingYarnAppStatus() throws Exception {
when(yarnClient.createApplication().getNewApplicationResponse().getApplicationId()).thenReturn(appId1);
when(yarnClient.getApplicationReport(appId1)).thenReturn(mockReport);
TezYarnClient tezClient = new TezYarnClient(yarnClient);
- tezClient.init(new TezConfiguration(false), new YarnConfiguration());
+ tezClient.init(new TezConfiguration(false));
try {
tezClient.getApplicationReport(appId1);
fail("getApplicationReport should have thrown");
@@ -812,8 +940,7 @@ public void testAMClientHeartbeat() throws Exception {
Thread.sleep(1000);
}
client.stop();
- verify(client.sessionAmProxy, atLeast(3)).getAMStatus(any(RpcController.class),
- any(GetAMStatusRequestProto.class));
+ verify(client.sessionAmProxy, atLeast(3)).getAMStatus(any(), any());
conf.setInt(TezConfiguration.TEZ_AM_CLIENT_HEARTBEAT_TIMEOUT_SECS, -1);
final TezClientForTest client2 = configureAndCreateTezClient(conf);
@@ -826,10 +953,7 @@ public void testAMClientHeartbeat() throws Exception {
Thread.sleep(1000);
}
client2.stop();
- verify(client2.sessionAmProxy, times(0)).getAMStatus(any(RpcController.class),
- any(GetAMStatusRequestProto.class));
-
-
+ verify(client2.sessionAmProxy, times(0)).getAMStatus(any(), any());
}
@Test(timeout = 20000)
@@ -873,12 +997,31 @@ public void testAMHeartbeatFailOnGetAMStatus() throws Exception {
final TezClientForTest client = configureAndCreateTezClient(conf);
client.start();
- when(client.sessionAmProxy.getAMStatus(any(RpcController.class),
- any(GetAMStatusRequestProto.class))).thenThrow(new ServiceException("error"));
+ when(client.sessionAmProxy.getAMStatus(any(), any())).thenThrow(new ServiceException("error"));
client.callRealGetSessionAMProxy = true;
when(client.mockYarnClient.getApplicationReport(client.mockAppId).getYarnApplicationState())
.thenReturn(YarnApplicationState.FAILED);
Thread.sleep(3 * amHeartBeatTimeoutSecs * 1000);
assertTrue(client.getAMKeepAliveService().isTerminated());
}
+
+ //See TEZ-3874
+ @Test(timeout = 5000)
+ public void testYarnZkDeprecatedConf() {
+ Configuration conf = new Configuration(false);
+ String val = "hostname:2181";
+ conf.set("yarn.resourcemanager.zk-address", val);
+
+ //Test that Exception is not thrown by createFinalConfProtoForApp
+ TezClientUtils.createFinalConfProtoForApp(conf, null);
+ }
+
+ @Test
+ public void testGetAmHostAndPort() throws Exception {
+ final TezClientForTest client = configureAndCreateTezClient(new TezConfiguration());
+
+ // TezClient exposes AM host and port from the FrameworkClient (now it's a TezYarnClientForTest)
+ assertEquals("testhost", client.getAmHost());
+ assertEquals(1234, client.getAmPort());
+ }
}
diff --git a/tez-api/src/test/java/org/apache/tez/client/TestTezClientUtils.java b/tez-api/src/test/java/org/apache/tez/client/TestTezClientUtils.java
index 7ff8125768..a2f1ce1175 100644
--- a/tez-api/src/test/java/org/apache/tez/client/TestTezClientUtils.java
+++ b/tez-api/src/test/java/org/apache/tez/client/TestTezClientUtils.java
@@ -26,8 +26,8 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
-import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -47,8 +47,10 @@
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.io.DataInputByteBuffer;
+import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.hadoop.yarn.api.ApplicationConstants.Environment;
import org.apache.hadoop.yarn.api.records.ApplicationId;
@@ -81,6 +83,8 @@
public class TestTezClientUtils {
private static String TEST_ROOT_DIR = "target" + Path.SEPARATOR
+ TestTezClientUtils.class.getName() + "-tmpDir";
+ private static final File STAGING_DIR = new File(System.getProperty("test.build.data", "target"),
+ TestTezClientUtils.class.getName()).getAbsoluteFile();
/**
*
*/
@@ -128,12 +132,29 @@ public void validateSetTezJarLocalResourcesDefinedNonExistingDirectory() throws
TezClientUtils.setupTezJarsLocalResources(conf, credentials, resources);
}
- /**
- *
- */
- @Test (timeout=10000)
+ private static List getDirAndFileURL() throws MalformedURLException {
+ String[] classpaths = System.getProperty("java.class.path")
+ .split(System.getProperty("path.separator"));
+ List urls = new ArrayList<>(2);
+ File lastFile = null;
+ // Add one file and one directory.
+ for (String path : classpaths) {
+ URL url = new URL("file://" + path);
+ File file = FileUtils.toFile(url);
+ if (lastFile == null) {
+ lastFile = file;
+ urls.add(url);
+ } else if (lastFile.isDirectory() != file.isDirectory()) {
+ urls.add(url);
+ break;
+ }
+ }
+ return urls;
+ }
+
+ @Test (timeout=20000)
public void validateSetTezJarLocalResourcesDefinedExistingDirectory() throws Exception {
- URL[] cp = ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();
+ List cp = getDirAndFileURL();
StringBuffer buffer = new StringBuffer();
for (URL url : cp) {
buffer.append(url.toExternalForm());
@@ -147,22 +168,27 @@ public void validateSetTezJarLocalResourcesDefinedExistingDirectory() throws Exc
localizedMap);
Assert.assertFalse(usingArchive);
Set resourceNames = localizedMap.keySet();
+ boolean assertedDir = false;
+ boolean assertedFile = false;
for (URL url : cp) {
File file = FileUtils.toFile(url);
- if (file.isDirectory()){
+ if (file.isDirectory()) {
String[] firList = file.list();
for (String fileNme : firList) {
File innerFile = new File(file, fileNme);
if (!innerFile.isDirectory()){
assertTrue(resourceNames.contains(innerFile.getName()));
+ assertedDir = true;
}
// not supporting deep hierarchies
}
- }
- else {
+ } else {
assertTrue(resourceNames.contains(file.getName()));
+ assertedFile = true;
}
}
+ assertTrue(assertedDir);
+ assertTrue(assertedFile);
}
/**
@@ -171,7 +197,7 @@ public void validateSetTezJarLocalResourcesDefinedExistingDirectory() throws Exc
*/
@Test (timeout=5000)
public void validateSetTezJarLocalResourcesDefinedExistingDirectoryIgnored() throws Exception {
- URL[] cp = ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();
+ List cp = getDirAndFileURL();
StringBuffer buffer = new StringBuffer();
for (URL url : cp) {
buffer.append(url.toExternalForm());
@@ -190,9 +216,9 @@ public void validateSetTezJarLocalResourcesDefinedExistingDirectoryIgnored() thr
*
* @throws Exception
*/
- @Test (timeout=5000)
+ @Test (timeout=20000)
public void validateSetTezJarLocalResourcesDefinedExistingDirectoryIgnoredSetToFalse() throws Exception {
- URL[] cp = ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();
+ List cp = getDirAndFileURL();
StringBuffer buffer = new StringBuffer();
for (URL url : cp) {
buffer.append(url.toExternalForm());
@@ -328,6 +354,7 @@ public void validateSetTezJarLocalResourcesMixTarballAndJar() throws Exception {
// ApplicationSubmissionContext
public void testAppSubmissionContextForPriority() throws Exception {
TezConfiguration tezConf = new TezConfiguration();
+ tezConf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGING_DIR.getAbsolutePath());
int testpriority = 999;
ApplicationId appId = ApplicationId.newInstance(1000, 1);
Credentials credentials = new Credentials();
@@ -378,9 +405,10 @@ public void testSetApplicationTags() {
public void testSessionTokenInAmClc() throws IOException, YarnException {
TezConfiguration tezConf = new TezConfiguration();
+ tezConf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGING_DIR.getAbsolutePath());
ApplicationId appId = ApplicationId.newInstance(1000, 1);
- DAG dag = DAG.create("testdag");
+ DAG dag = DAG.create("testdag-testSessionTokenInAmClc");
dag.addVertex(Vertex.create("testVertex", ProcessorDescriptor.create("processorClassname"), 1)
.setTaskLaunchCmdOpts("initialLaunchOpts"));
@@ -415,12 +443,13 @@ public void testAMLoggingOptsSimple() throws IOException, YarnException {
TezConfiguration tezConf = new TezConfiguration();
tezConf.set(TezConfiguration.TEZ_AM_LOG_LEVEL, "WARN");
+ tezConf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGING_DIR.getAbsolutePath());
ApplicationId appId = ApplicationId.newInstance(1000, 1);
Credentials credentials = new Credentials();
JobTokenSecretManager jobTokenSecretManager = new JobTokenSecretManager();
TezClientUtils.createSessionToken(appId.toString(), jobTokenSecretManager, credentials);
- DAG dag = DAG.create("testdag");
+ DAG dag = DAG.create("DAG-testAMLoggingOptsSimple");
dag.addVertex(Vertex.create("testVertex", ProcessorDescriptor.create("processorClassname"), 1)
.setTaskLaunchCmdOpts("initialLaunchOpts"));
AMConfiguration amConf =
@@ -455,12 +484,13 @@ public void testAMLoggingOptsPerLogger() throws IOException, YarnException {
TezConfiguration tezConf = new TezConfiguration();
tezConf.set(TezConfiguration.TEZ_AM_LOG_LEVEL,
"WARN;org.apache.hadoop.ipc=DEBUG;org.apache.hadoop.security=DEBUG");
+ tezConf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGING_DIR.getAbsolutePath());
ApplicationId appId = ApplicationId.newInstance(1000, 1);
Credentials credentials = new Credentials();
JobTokenSecretManager jobTokenSecretManager = new JobTokenSecretManager();
TezClientUtils.createSessionToken(appId.toString(), jobTokenSecretManager, credentials);
- DAG dag = DAG.create("testdag");
+ DAG dag = DAG.create("DAG-testAMLoggingOptsPerLogger");
dag.addVertex(Vertex.create("testVertex", ProcessorDescriptor.create("processorClassname"), 1)
.setTaskLaunchCmdOpts("initialLaunchOpts"));
AMConfiguration amConf =
@@ -652,6 +682,17 @@ public void testDefaultLoggingJavaOpts() {
javaOpts.contains("-Dlog4j.configuratorClass=org.apache.tez.common.TezLog4jConfigurator"));
}
+ @Test
+ public void testDefaultLoggingJavaOptsWithRootLogger() {
+ String origJavaOpts = "-D" + TezConstants.TEZ_ROOT_LOGGER_NAME + "=INFO -DtestProperty=value";
+ String javaOpts = TezClientUtils.maybeAddDefaultLoggingJavaOpts("FOOBAR", origJavaOpts);
+ Assert.assertNotNull(javaOpts);
+ Assert.assertTrue(javaOpts.contains("-D" + TezConstants.TEZ_ROOT_LOGGER_NAME + "=FOOBAR"));
+ Assert.assertTrue(javaOpts.contains(TezConstants.TEZ_CONTAINER_LOG4J_PROPERTIES_FILE)
+ && javaOpts.contains("-Dlog4j.configuratorClass=org.apache.tez.common.TezLog4jConfigurator"));
+ Assert.assertTrue(javaOpts.contains("-DtestProperty=value"));
+ }
+
@Test (timeout = 5000)
public void testConfSerializationForAm() {
Configuration conf =new Configuration(false);
@@ -890,5 +931,29 @@ public void testClusterTaskLaunchCmdOptsSetup() throws TezException {
}
+ @Test
+ public void testSessionCredentialsMergedBeforeAmConfigCredentials() throws Exception {
+ TezConfiguration conf = new TezConfiguration();
+ Text tokenType = new Text("TEST_TOKEN_TYPE");
+ Text tokenKind = new Text("TEST_TOKEN_KIND");
+ Text tokenService = new Text("TEST_TOKEN_SERVICE");
+
+ Credentials amConfigCredentials = new Credentials();
+ amConfigCredentials.addToken(tokenType,
+ new Token<>("id1".getBytes(), null, tokenKind, tokenService));
+
+ Credentials sessionCredentials = new Credentials();
+ Token sessionToken =
+ new Token<>("id2".getBytes(), null, tokenKind, tokenService);
+ sessionCredentials.addToken(tokenType, sessionToken);
+
+ AMConfiguration amConfig = new AMConfiguration(conf, null, amConfigCredentials);
+ Credentials amLaunchCredentials =
+ TezClientUtils.prepareAmLaunchCredentials(amConfig, sessionCredentials, conf, null);
+
+ // if there is another token in am conf creds of the same token type,
+ // session token should be applied while creating ContainerLaunchContext
+ Assert.assertEquals(sessionToken, amLaunchCredentials.getToken(tokenType));
+ }
}
diff --git a/tez-api/src/test/java/org/apache/tez/common/TestReflectionUtils.java b/tez-api/src/test/java/org/apache/tez/common/TestReflectionUtils.java
index 2fbd35cb3d..ed3814d000 100644
--- a/tez-api/src/test/java/org/apache/tez/common/TestReflectionUtils.java
+++ b/tez-api/src/test/java/org/apache/tez/common/TestReflectionUtils.java
@@ -58,7 +58,7 @@ public void testConstructorWithParameters() throws TezReflectionException
@Test(timeout = 5000)
public void testAddResourceToClasspath() throws IOException, TezException {
-
+ TezClassLoader.setupTezClassLoader();
String rsrcName = "dummyfile.xml";
FileSystem localFs = FileSystem.getLocal(new Configuration());
Path p = new Path(rsrcName);
@@ -78,7 +78,7 @@ public void testAddResourceToClasspath() throws IOException, TezException {
urlForm = urlForm.substring(0, urlForm.lastIndexOf('/') + 1);
URL url = new URL(urlForm);
- ReflectionUtils.addResourcesToClasspath(Collections.singletonList(url));
+ ReflectionUtils.addResourcesToSystemClassLoader(Collections.singletonList(url));
loadedUrl = Thread.currentThread().getContextClassLoader().getResource(rsrcName);
diff --git a/tez-api/src/test/java/org/apache/tez/common/TestTezCommonUtils.java b/tez-api/src/test/java/org/apache/tez/common/TestTezCommonUtils.java
index 3929c4bf5a..e1ae6cd2cb 100644
--- a/tez-api/src/test/java/org/apache/tez/common/TestTezCommonUtils.java
+++ b/tez-api/src/test/java/org/apache/tez/common/TestTezCommonUtils.java
@@ -18,6 +18,7 @@
package org.apache.tez.common;
+import java.io.File;
import java.io.IOException;
import java.util.Map;
@@ -25,6 +26,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.MiniDFSCluster;
@@ -43,8 +45,11 @@
public class TestTezCommonUtils {
private static final String STAGE_DIR = "/tmp/mystage";
+
+ private static final File LOCAL_STAGING_DIR = new File(System.getProperty("test.build.data"),
+ TestTezCommonUtils.class.getSimpleName()).getAbsoluteFile();
private static String RESOLVED_STAGE_DIR;
- private static Configuration conf = new Configuration();;
+ private static Configuration conf = new Configuration();
private static String TEST_ROOT_DIR = "target" + Path.SEPARATOR
+ TestTezCommonUtils.class.getName() + "-tmpDir";
private static MiniDFSCluster dfsCluster = null;
@@ -84,10 +89,10 @@ public static void afterClass() throws InterruptedException {
public void testTezBaseStagingPath() throws Exception {
Configuration localConf = new Configuration();
// Check if default works with localFS
- localConf.unset(TezConfiguration.TEZ_AM_STAGING_DIR);
+ localConf.set(TezConfiguration.TEZ_AM_STAGING_DIR, LOCAL_STAGING_DIR.getAbsolutePath());
localConf.set("fs.defaultFS", "file:///");
Path stageDir = TezCommonUtils.getTezBaseStagingPath(localConf);
- Assert.assertEquals(stageDir.toString(), "file:" + TezConfiguration.TEZ_AM_STAGING_DIR_DEFAULT);
+ Assert.assertEquals("file:" + LOCAL_STAGING_DIR, stageDir.toString());
// check if user set something, indeed works
conf.set(TezConfiguration.TEZ_AM_STAGING_DIR, STAGE_DIR);
@@ -409,4 +414,17 @@ public void testGetDAGSessionTimeout() {
}
+ @Test
+ public void testMkDirForAM() throws IOException {
+ Configuration remoteConf = new Configuration();
+ remoteConf.set(MiniDFSCluster.HDFS_MINIDFS_BASEDIR, TEST_ROOT_DIR);
+ remoteConf.set(CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY, "777");
+ MiniDFSCluster miniDFS = new MiniDFSCluster.Builder(remoteConf).numDataNodes(3).format(true).racks(null)
+ .build();
+ FileSystem remoteFileSystem = miniDFS.getFileSystem();
+ Path path = new Path(TEST_ROOT_DIR + "/testMkDirForAM");
+ TezCommonUtils.mkDirForAM(remoteFileSystem, path);
+ Assert.assertEquals(TezCommonUtils.TEZ_AM_DIR_PERMISSION, remoteFileSystem.getFileStatus(path).getPermission());
+ miniDFS.shutdown();
+ }
}
diff --git a/tez-api/src/test/java/org/apache/tez/common/TestVersionInfo.java b/tez-api/src/test/java/org/apache/tez/common/TestVersionInfo.java
index 17ff3d1655..67f97b86a5 100644
--- a/tez-api/src/test/java/org/apache/tez/common/TestVersionInfo.java
+++ b/tez-api/src/test/java/org/apache/tez/common/TestVersionInfo.java
@@ -18,44 +18,41 @@
package org.apache.tez.common;
-import java.io.IOException;
-
import org.junit.Assert;
import org.junit.Test;
-
public class TestVersionInfo {
- final String version = "0.6.0-SNAPSHOT";
- final String revision = "d523db65804a5742ce50824e6fcfb8a04d184c0d";
- final String buildTime = "20141024-1052";
- final String scmUrl = "scm:git:https://git-wip-us.apache.org/repos/asf/tez.git";
+ private static final String VERSION = "0.6.0-SNAPSHOT";
+ private static final String REVISION = "d523db65804a5742ce50824e6fcfb8a04d184c0d";
+ private static final String BUILD_TIME = "20141024-1052";
+ private static final String SCM_URL = "scm:git:https://gitbox.apache.org/repos/asf/tez.git";
@Test(timeout = 5000)
public void testTest1File() {
VersionInfo versionInfo = new VersionInfo("test1");
- Assert.assertEquals(version, versionInfo.getVersion());
- Assert.assertEquals(revision, versionInfo.getRevision());
- Assert.assertEquals(buildTime, versionInfo.getBuildTime());
- Assert.assertEquals(scmUrl, versionInfo.getSCMURL());
+ Assert.assertEquals(VERSION, versionInfo.getVersion());
+ Assert.assertEquals(REVISION, versionInfo.getRevision());
+ Assert.assertEquals(BUILD_TIME, versionInfo.getBuildTime());
+ Assert.assertEquals(SCM_URL, versionInfo.getSCMURL());
}
@Test(timeout = 5000)
public void testTest2File() {
VersionInfo versionInfo = new VersionInfo("test2");
- Assert.assertEquals(version, versionInfo.getVersion());
- Assert.assertEquals(revision, versionInfo.getRevision());
- Assert.assertEquals(buildTime, versionInfo.getBuildTime());
+ Assert.assertEquals(VERSION, versionInfo.getVersion());
+ Assert.assertEquals(REVISION, versionInfo.getRevision());
+ Assert.assertEquals(BUILD_TIME, versionInfo.getBuildTime());
Assert.assertEquals(VersionInfo.UNKNOWN, versionInfo.getSCMURL());
}
@Test(timeout = 5000)
public void testTest3File() {
VersionInfo versionInfo = new VersionInfo("test3");
- Assert.assertEquals(version, versionInfo.getVersion());
- Assert.assertEquals(revision, versionInfo.getRevision());
+ Assert.assertEquals(VERSION, versionInfo.getVersion());
+ Assert.assertEquals(REVISION, versionInfo.getRevision());
Assert.assertEquals("", versionInfo.getBuildTime());
- Assert.assertEquals(scmUrl, versionInfo.getSCMURL());
+ Assert.assertEquals(SCM_URL, versionInfo.getSCMURL());
}
@Test(timeout = 5000)
diff --git a/tez-api/src/test/java/org/apache/tez/common/security/TestTokenCache.java b/tez-api/src/test/java/org/apache/tez/common/security/TestTokenCache.java
index 59488b6fb8..4c144174c7 100644
--- a/tez-api/src/test/java/org/apache/tez/common/security/TestTokenCache.java
+++ b/tez-api/src/test/java/org/apache/tez/common/security/TestTokenCache.java
@@ -18,7 +18,7 @@
package org.apache.tez.common.security;
-import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -113,6 +113,11 @@ public void testObtainTokensForFileSystems() throws Exception {
conf.setBoolean("fs.test.impl.disable.cache", true);
TokenCache.obtainTokensForFileSystemsInternal(creds, paths, conf);
verify(TestFileSystem.fs, times(paths.length + 1)).addDelegationTokens(renewer, creds);
+
+ // Excluded filesystem tokens should not be obtained.
+ conf.set("tez.job.fs-servers.token-renewal.exclude", "dir");
+ TokenCache.obtainTokensForFileSystemsInternal(creds, paths, conf);
+ verify(TestFileSystem.fs, times(paths.length + 1)).addDelegationTokens(renewer, creds);
}
private Path[] makePaths(int count, String prefix) throws Exception {
@@ -127,7 +132,7 @@ public static class TestFileSystem extends FilterFileSystem {
static final FileSystem fs = mock(FileSystem.class);
static {
try {
- when(fs.getUri()).thenReturn(new URI("test:///"));
+ when(fs.getUri()).thenReturn(new URI("test://dir"));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
@@ -148,7 +153,7 @@ private MockFileSystem createFileSystemForServiceName(final String service)
throws IOException {
MockFileSystem mockFs = new MockFileSystem();
when(mockFs.getCanonicalServiceName()).thenReturn(service);
- when(mockFs.getDelegationToken(any(String.class))).thenAnswer(
+ when(mockFs.getDelegationToken(any())).thenAnswer(
new Answer>() {
int unique = 0;
@Override
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAG.java b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAG.java
index 05c4e30cf0..5ec57c4148 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAG.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAG.java
@@ -47,7 +47,7 @@ public void testDuplicatedVertices() {
dummyTaskCount, dummyTaskResource);
Vertex v2 = Vertex.create("v1", ProcessorDescriptor.create("Processor"),
dummyTaskCount, dummyTaskResource);
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDuplicatedVertices");
dag.addVertex(v1);
try {
dag.addVertex(v2);
@@ -74,7 +74,7 @@ public void testDuplicatedEdges() {
SchedulingType.CONCURRENT, OutputDescriptor.create("output"),
InputDescriptor.create("input")));
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDuplicatedEdges");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(edge1);
@@ -96,7 +96,7 @@ public void testDuplicatedVertexGroup() {
Vertex v3 = Vertex.create("v3", ProcessorDescriptor.create("Processor"),
dummyTaskCount, dummyTaskResource);
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDuplicatedVertexGroup");
dag.createVertexGroup("group_1", v1, v2);
try {
@@ -123,7 +123,7 @@ public void testDuplicatedGroupInputEdge() {
ProcessorDescriptor.create("Processor"),
dummyTaskCount, dummyTaskResource);
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testDuplicatedGroupInputEdge");
String groupName1 = "uv12";
VertexGroup uv12 = dag.createVertexGroup(groupName1, v1, v2);
@@ -156,7 +156,7 @@ public void testDuplicatedGroupInputEdge() {
@Test(timeout = 5000)
public void testDAGConf() {
- DAG dag = DAG.create("dag1");
+ DAG dag = DAG.create("DAG-testDAGConf");
// it's OK to set custom configuration
dag.setConf("unknown_conf", "value");
@@ -281,7 +281,7 @@ public void testDuplicatedOutput_1() {
@Test(timeout = 5000)
public void testDuplicatedOutput_2() {
- DAG dag = DAG.create("dag1");
+ DAG dag = DAG.create("DAG-testDuplicatedOutput_2");
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create("dummyProcessor"));
DataSinkDescriptor dataSink =
DataSinkDescriptor.create(OutputDescriptor.create("dummyOutput"), null, null);
@@ -354,7 +354,7 @@ public void testRecreateDAG() {
Resource.newInstance(1, 1));
Vertex v2 = Vertex.create("v2", ProcessorDescriptor.create("dummyProcessor2"), 1,
Resource.newInstance(1, 1));
- DAG dag = DAG.create("dag1").addVertex(v1).addVertex(v2).addTaskLocalFiles(lrDAG);
+ DAG dag = DAG.create("DAG-testRecreateDAG").addVertex(v1).addVertex(v2).addTaskLocalFiles(lrDAG);
TezConfiguration tezConf = new TezConfiguration();
DAGPlan firstPlan = dag.createDag(tezConf, null, null, null, false);
@@ -375,7 +375,7 @@ public void testCreateDAGForHistoryLogLevel() {
Resource.newInstance(1, 1));
Vertex v2 = Vertex.create("v2", ProcessorDescriptor.create("dummyProcessor2"), 1,
Resource.newInstance(1, 1));
- DAG dag = DAG.create("dag1").addVertex(v1).addVertex(v2).addTaskLocalFiles(lrDAG);
+ DAG dag = DAG.create("DAG-testCreateDAGForHistoryLogLevel").addVertex(v1).addVertex(v2).addTaskLocalFiles(lrDAG);
TezConfiguration tezConf = new TezConfiguration();
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGPlan.java b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGPlan.java
index 8e1011feb7..d5f6b0af9c 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGPlan.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGPlan.java
@@ -107,7 +107,7 @@ public void testBasicJobPlanSerde() throws IOException {
@Test(timeout = 5000)
public void testEdgeManagerSerde() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testEdgeManagerSerde");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1")
.setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
ProcessorDescriptor pd2 = ProcessorDescriptor.create("processor2")
@@ -144,7 +144,7 @@ public void testEdgeManagerSerde() {
@Test(timeout = 5000)
public void testUserPayloadSerde() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testUserPayloadSerde");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1").
setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
ProcessorDescriptor pd2 = ProcessorDescriptor.create("processor2").
@@ -205,7 +205,7 @@ public void testUserPayloadSerde() {
@Test(timeout = 5000)
public void userVertexOrderingIsMaintained() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-userVertexOrderingIsMaintained");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1").
setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
ProcessorDescriptor pd2 = ProcessorDescriptor.create("processor2").
@@ -278,7 +278,7 @@ public void userVertexOrderingIsMaintained() {
@Test (timeout=5000)
public void testCredentialsSerde() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testCredentialsSerde");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1").
setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
ProcessorDescriptor pd2 = ProcessorDescriptor.create("processor2").
@@ -322,7 +322,7 @@ public void testCredentialsSerde() {
@Test(timeout = 5000)
public void testInvalidExecContext_1() {
- DAG dag = DAG.create("dag1");
+ DAG dag = DAG.create("DAG-testInvalidExecContext_1");
dag.setExecutionContext(VertexExecutionContext.createExecuteInAm(true));
Vertex v1 = Vertex.create("testvertex", ProcessorDescriptor.create("processor1"), 1);
dag.addVertex(v1);
@@ -364,7 +364,7 @@ public void testInvalidExecContext_2() {
VertexExecutionContext.create("plugin", "plugin", "invalidplugin");
- DAG dag = DAG.create("dag1");
+ DAG dag = DAG.create("DAG-testInvalidExecContext_2");
dag.setExecutionContext(VertexExecutionContext.createExecuteInContainers(true));
Vertex v1 = Vertex.create("testvertex", ProcessorDescriptor.create("processor1"), 1);
dag.addVertex(v1);
@@ -429,7 +429,7 @@ public void testInvalidExecContext_2() {
@Test(timeout = 5000)
public void testServiceDescriptorPropagation() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testServiceDescriptorPropagation");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1").
setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
ProcessorDescriptor pd2 = ProcessorDescriptor.create("processor2").
@@ -492,7 +492,7 @@ public void testServiceDescriptorPropagation() {
@Test(timeout = 5000)
public void testInvalidJavaOpts() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testInvalidJavaOpts");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1")
.setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
Vertex v1 = Vertex.create("v1", pd1, 10, Resource.newInstance(1024, 1));
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGVerify.java b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGVerify.java
index e3c40aaef0..1ba877769f 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGVerify.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/TestDAGVerify.java
@@ -73,7 +73,7 @@ public void testVerifyScatterGather() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyScatterGather");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
@@ -94,7 +94,7 @@ public void testVerifyCustomEdge() {
SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyCustomEdge");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
@@ -114,13 +114,13 @@ public void testVerifyOneToOne() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOne");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
}
-
+
@Test(timeout = 5000)
// v1 (known) -> v2 (-1) -> v3 (-1)
public void testVerifyOneToOneInferParallelism() {
@@ -143,7 +143,7 @@ public void testVerifyOneToOneInferParallelism() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOneInferParallelism");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -153,7 +153,7 @@ public void testVerifyOneToOneInferParallelism() {
Assert.assertEquals(dummyTaskCount, v2.getParallelism());
Assert.assertEquals(dummyTaskCount, v3.getParallelism());
}
-
+
@Test(timeout = 5000)
// v1 (known) -> v2 (-1) -> v3 (-1)
// The test checks resiliency to ordering of the vertices/edges
@@ -177,7 +177,7 @@ public void testVerifyOneToOneInferParallelismReverseOrder() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOneInferParallelismReverseOrder");
dag.addVertex(v3);
dag.addVertex(v1);
dag.addVertex(v2);
@@ -187,7 +187,7 @@ public void testVerifyOneToOneInferParallelismReverseOrder() {
Assert.assertEquals(dummyTaskCount, v2.getParallelism());
Assert.assertEquals(dummyTaskCount, v3.getParallelism());
}
-
+
@Test(timeout = 5000)
public void testVerifyOneToOneNoInferParallelism() {
Vertex v1 = Vertex.create("v1",
@@ -204,14 +204,14 @@ public void testVerifyOneToOneNoInferParallelism() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOneNoInferParallelism");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
Assert.assertEquals(-1, v2.getParallelism());
}
-
+
@Test(timeout = 5000)
// v1 (-1) -> v2 (known) -> v3 (-1)
public void testVerifyOneToOneIncorrectParallelism1() {
@@ -234,7 +234,7 @@ public void testVerifyOneToOneIncorrectParallelism1() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOneIncorrectParallelism1");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -280,7 +280,7 @@ public void testVerifyOneToOneIncorrectParallelism2() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyOneToOneIncorrectParallelism2");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -290,13 +290,13 @@ public void testVerifyOneToOneIncorrectParallelism2() {
dag.addEdge(e3);
try {
dag.verify();
- Assert.assertTrue(false);
+ Assert.fail();
} catch (TezUncheckedException e) {
Assert.assertTrue(e.getMessage().contains(
"1-1 Edge. Destination vertex parallelism must match source vertex"));
}
}
-
+
@Test(timeout = 5000)
public void testVerifyBroadcast() {
Vertex v1 = Vertex.create("v1",
@@ -310,14 +310,14 @@ public void testVerifyBroadcast() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerifyBroadcast");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
}
- @Test(expected = IllegalStateException.class, timeout = 5000)
+ @Test(timeout = 5000)
public void testVerify3() {
Vertex v1 = Vertex.create("v1",
ProcessorDescriptor.create(dummyProcessorClassName),
@@ -330,14 +330,14 @@ public void testVerify3() {
DataSourceType.EPHEMERAL, SchedulingType.SEQUENTIAL,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerify3");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
}
- @Test(expected = IllegalStateException.class, timeout = 5000)
+ @Test(timeout = 5000)
public void testVerify4() {
Vertex v1 = Vertex.create("v1",
ProcessorDescriptor.create(dummyProcessorClassName),
@@ -350,7 +350,7 @@ public void testVerify4() {
DataSourceType.EPHEMERAL, SchedulingType.CONCURRENT,
OutputDescriptor.create(dummyOutputClassName),
InputDescriptor.create(dummyInputClassName)));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testVerify4");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
@@ -397,7 +397,7 @@ public void testCycle1() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testCycle1");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -457,7 +457,7 @@ public void testCycle2() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testCycle2");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -489,7 +489,7 @@ public void testSelfCycle(){
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testSelfCycle");
dag.addVertex(v1);
dag.addEdge(e1);
try{
@@ -513,7 +513,7 @@ public void repeatedVertexName() {
ProcessorDescriptor.create("MapProcessor"),
dummyTaskCount, dummyTaskResource);
try {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-repeatedVertexName");
dag.addVertex(v1);
dag.addVertex(v1repeat);
dag.verify();
@@ -525,7 +525,7 @@ public void repeatedVertexName() {
System.out.println(ex.getMessage());
Assert.assertTrue(ex.getMessage().startsWith("Vertex v1 already defined"));
}
-
+
@Test(expected = IllegalStateException.class, timeout = 5000)
public void testInputAndInputVertexNameCollision() {
Vertex v1 = Vertex.create("v1",
@@ -534,22 +534,22 @@ public void testInputAndInputVertexNameCollision() {
Vertex v2 = Vertex.create("v2",
ProcessorDescriptor.create("MapProcessor"),
dummyTaskCount, dummyTaskResource);
-
+
v2.addDataSource("v1", DataSourceDescriptor.create(null, null, null));
-
+
Edge e1 = Edge.create(v1, v2,
EdgeProperty.create(DataMovementType.SCATTER_GATHER,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testInputAndInputVertexNameCollision");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
}
-
+
@Test(expected = IllegalStateException.class, timeout = 5000)
public void testOutputAndOutputVertexNameCollision() {
Vertex v1 = Vertex.create("v1",
@@ -558,22 +558,22 @@ public void testOutputAndOutputVertexNameCollision() {
Vertex v2 = Vertex.create("v2",
ProcessorDescriptor.create("MapProcessor"),
dummyTaskCount, dummyTaskResource);
-
+
v1.addDataSink("v2", DataSinkDescriptor.create(null, null, null));
-
+
Edge e1 = Edge.create(v1, v2,
EdgeProperty.create(DataMovementType.SCATTER_GATHER,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testOutputAndOutputVertexNameCollision");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addEdge(e1);
dag.verify();
}
-
+
@Test(expected = IllegalStateException.class, timeout = 5000)
public void testOutputAndVertexNameCollision() {
Vertex v1 = Vertex.create("v1",
@@ -582,15 +582,15 @@ public void testOutputAndVertexNameCollision() {
Vertex v2 = Vertex.create("v2",
ProcessorDescriptor.create("MapProcessor"),
dummyTaskCount, dummyTaskResource);
-
+
v1.addDataSink("v2", DataSinkDescriptor.create(null, null, null));
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testOutputAndVertexNameCollision");
dag.addVertex(v1);
dag.addVertex(v2);
dag.verify();
}
-
+
@Test(expected = IllegalStateException.class, timeout = 5000)
public void testInputAndVertexNameCollision() {
Vertex v1 = Vertex.create("v1",
@@ -599,10 +599,10 @@ public void testInputAndVertexNameCollision() {
Vertex v2 = Vertex.create("v2",
ProcessorDescriptor.create("MapProcessor"),
dummyTaskCount, dummyTaskResource);
-
+
v1.addDataSource("v2", DataSourceDescriptor.create(null, null, null));
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testInputAndVertexNameCollision");
dag.addVertex(v1);
dag.addVertex(v2);
dag.verify();
@@ -632,7 +632,7 @@ public void BinaryInputAllowed() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-BinaryInputAllowed");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -640,7 +640,7 @@ public void BinaryInputAllowed() {
dag.addEdge(e2);
dag.verify();
}
-
+
@Test(timeout = 5000)
public void testVertexGroupWithMultipleOutputEdges() {
Vertex v1 = Vertex.create("v1",
@@ -655,19 +655,19 @@ public void testVertexGroupWithMultipleOutputEdges() {
Vertex v4 = Vertex.create("v4",
ProcessorDescriptor.create("Processor"),
dummyTaskCount, dummyTaskResource);
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testVertexGroupWithMultipleOutputEdges");
VertexGroup uv12 = dag.createVertexGroup("uv12", v1, v2);
OutputDescriptor outDesc = new OutputDescriptor();
uv12.addDataSink("uvOut", DataSinkDescriptor.create(outDesc, null, null));
-
+
GroupInputEdge e1 = GroupInputEdge.create(uv12, v3,
EdgeProperty.create(DataMovementType.SCATTER_GATHER,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")),
InputDescriptor.create("dummy input class"));
-
+
GroupInputEdge e2 = GroupInputEdge.create(uv12, v4,
EdgeProperty.create(DataMovementType.SCATTER_GATHER,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
@@ -685,7 +685,7 @@ public void testVertexGroupWithMultipleOutputEdges() {
for (int i = 0; i< 10;++i){
dag.verify(); // should be OK when called multiple times
}
-
+
Assert.assertEquals(2, v1.getOutputVertices().size());
Assert.assertEquals(2, v2.getOutputVertices().size());
Assert.assertTrue(v1.getOutputVertices().contains(v3));
@@ -693,7 +693,7 @@ public void testVertexGroupWithMultipleOutputEdges() {
Assert.assertTrue(v2.getOutputVertices().contains(v3));
Assert.assertTrue(v2.getOutputVertices().contains(v4));
}
-
+
@Test(timeout = 5000)
public void testVertexGroup() {
Vertex v1 = Vertex.create("v1",
@@ -711,16 +711,16 @@ public void testVertexGroup() {
Vertex v5 = Vertex.create("v5",
ProcessorDescriptor.create("Processor"),
dummyTaskCount, dummyTaskResource);
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testVertexGroup");
String groupName1 = "uv12";
VertexGroup uv12 = dag.createVertexGroup(groupName1, v1, v2);
OutputDescriptor outDesc = new OutputDescriptor();
uv12.addDataSink("uvOut", DataSinkDescriptor.create(outDesc, null, null));
-
+
String groupName2 = "uv23";
VertexGroup uv23 = dag.createVertexGroup(groupName2, v2, v3);
-
+
GroupInputEdge e1 = GroupInputEdge.create(uv12, v4,
EdgeProperty.create(DataMovementType.SCATTER_GATHER,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
@@ -733,7 +733,7 @@ public void testVertexGroup() {
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")),
InputDescriptor.create("dummy input class"));
-
+
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -744,7 +744,7 @@ public void testVertexGroup() {
for (int i = 0; i< 10;++i){
dag.verify(); // should be OK when called multiple times
}
-
+
// for the first Group v1 and v2 should get connected to v4 and also have 1 output
// for the second Group v2 and v3 should get connected to v5
// the Group place holders should disappear
@@ -775,7 +775,7 @@ public void testVertexGroup() {
Assert.assertTrue(v5.getGroupInputs().containsKey(groupName2));
Assert.assertEquals(2, dag.vertexGroups.size());
}
-
+
@Test(timeout = 5000)
public void testVertexGroupOneToOne() {
Vertex v1 = Vertex.create("v1",
@@ -793,16 +793,16 @@ public void testVertexGroupOneToOne() {
Vertex v5 = Vertex.create("v5",
ProcessorDescriptor.create("Processor"),
-1, dummyTaskResource);
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testVertexGroupOneToOne");
String groupName1 = "uv12";
VertexGroup uv12 = dag.createVertexGroup(groupName1, v1, v2);
OutputDescriptor outDesc = new OutputDescriptor();
uv12.addDataSink("uvOut", DataSinkDescriptor.create(outDesc, null, null));
-
+
String groupName2 = "uv23";
VertexGroup uv23 = dag.createVertexGroup(groupName2, v2, v3);
-
+
GroupInputEdge e1 = GroupInputEdge.create(uv12, v4,
EdgeProperty.create(DataMovementType.ONE_TO_ONE,
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
@@ -815,7 +815,7 @@ public void testVertexGroupOneToOne() {
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")),
InputDescriptor.create("dummy input class"));
-
+
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -826,7 +826,7 @@ public void testVertexGroupOneToOne() {
for (int i = 0; i< 10;++i){
dag.verify(); // should be OK when called multiple times
}
-
+
Assert.assertEquals(dummyTaskCount, v5.getParallelism());
}
@@ -856,7 +856,7 @@ public void BinaryOutput() {
DataSourceType.PERSISTED, SchedulingType.SEQUENTIAL,
OutputDescriptor.create("dummy output class"),
InputDescriptor.create("dummy input class")));
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-BinaryOutput");
dag.addVertex(v1);
dag.addVertex(v2);
dag.addVertex(v3);
@@ -874,7 +874,7 @@ public void BinaryOutput() {
public void testDagWithNoVertices() {
IllegalStateException ex=null;
try {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testDagWithNoVertices");
dag.verify();
}
catch (IllegalStateException e){
@@ -921,7 +921,7 @@ public void testInvalidVertexConstruction() {
@Test(timeout = 5000)
public void testMultipleRootInputsAllowed() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testMultipleRootInputsAllowed");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1")
.setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
Vertex v1 = Vertex.create("v1", pd1, 10, Resource.newInstance(1024, 1));
@@ -941,8 +941,8 @@ public void testMultipleRootInputsAllowed() {
dag.createDag(new TezConfiguration(), null, null, null, true);
}
-
-
+
+
@Test(timeout = 5000)
public void testDAGCreateDataInference() {
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
@@ -954,7 +954,7 @@ public void testDAGCreateDataInference() {
String lrName2 = "LR2";
lrs2.put(lrName2, LocalResource.newInstance(URL.newInstance("file", "localhost", 0, "/test1"),
LocalResourceType.FILE, LocalResourceVisibility.PUBLIC, 1, 1));
-
+
Set hosts = Sets.newHashSet();
hosts.add("h1");
hosts.add("h2");
@@ -962,11 +962,11 @@ public void testDAGCreateDataInference() {
taskLocationHints.add(TaskLocationHint.createTaskLocationHint(hosts, null));
taskLocationHints.add(TaskLocationHint.createTaskLocationHint(hosts, null));
VertexLocationHint vLoc = VertexLocationHint.create(taskLocationHints);
- DataSourceDescriptor ds = DataSourceDescriptor.create(InputDescriptor.create("I.class"),
+ DataSourceDescriptor ds = DataSourceDescriptor.create(InputDescriptor.create("I.class"),
InputInitializerDescriptor.create(dummyInputInitClassName), dummyTaskCount, null, vLoc, lrs2);
v1.addDataSource("i1", ds);
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testDAGCreateDataInference");
dag.addVertex(v1);
dag.addTaskLocalFiles(lrs1);
DAGPlan dagPlan = dag.createDag(new TezConfiguration(), null, null, null, true);
@@ -1003,11 +1003,11 @@ public void testInferredFilesFail() {
Assert.assertTrue(e.getMessage().contains("Duplicate Resources found with different size"));
}
- DataSourceDescriptor ds = DataSourceDescriptor.create(InputDescriptor.create("I.class"),
+ DataSourceDescriptor ds = DataSourceDescriptor.create(InputDescriptor.create("I.class"),
null, -1, null, null, lrs2);
v1.addDataSource("i1", ds);
-
- DAG dag = DAG.create("testDag");
+
+ DAG dag = DAG.create("DAG-testInferredFilesFail");
dag.addVertex(v1);
dag.addTaskLocalFiles(lrs);
try {
@@ -1024,10 +1024,10 @@ public void testInferredFilesFail() {
Assert.assertTrue(e.getMessage().contains("Duplicate Resources found with different size"));
}
}
-
+
@Test(timeout = 5000)
public void testDAGAccessControls() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testDAGAccessControls");
ProcessorDescriptor pd1 = ProcessorDescriptor.create("processor1")
.setUserPayload(UserPayload.create(ByteBuffer.wrap("processor1Bytes".getBytes())));
Vertex v1 = Vertex.create("v1", pd1, 10, Resource.newInstance(1024, 1));
@@ -1055,7 +1055,7 @@ public void testDAGAccessControls() {
// v1 has input initializer
@Test(timeout = 5000)
public void testDAGInvalidParallelism1() {
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDAGInvalidParallelism1");
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
dag.addVertex(v1);
try {
@@ -1076,7 +1076,7 @@ public void testDAGInvalidParallelism1() {
// v1 has custom vertex manager
@Test(timeout = 5000)
public void testDAGInvalidParallelism2() {
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDAGInvalidParallelism2");
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
dag.addVertex(v1);
try {
@@ -1095,7 +1095,7 @@ public void testDAGInvalidParallelism2() {
// v1 has 1-1 united source vertex v0 which has input initializer
@Test(timeout = 5000)
public void testDAGInvalidParallelism3() {
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDAGInvalidParallelism3");
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
dag.addVertex(v1);
try {
@@ -1122,7 +1122,7 @@ public void testDAGInvalidParallelism3() {
// v1 has an 1-1 united parent v0 which has custom vertex manager
@Test//(timeout = 5000)
public void testDAGInvalidParallelism4() {
- DAG dag = DAG.create("testDAG");
+ DAG dag = DAG.create("DAG-testDAGInvalidParallelism4");
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
dag.addVertex(v1);
try {
@@ -1146,7 +1146,7 @@ public void testDAGInvalidParallelism4() {
@Test
public void testDAGWithSplitsOnClient() {
- DAG dag = DAG.create("testDag");
+ DAG dag = DAG.create("DAG-testDAGWithSplitsOnClient");
// Mimic map which has a data source and shards set when splits are generated in the client
Vertex v1 = Vertex.create("v1", ProcessorDescriptor.create(dummyProcessorClassName));
@@ -1170,7 +1170,7 @@ public void testDAGWithSplitsOnClient() {
// Verifies failure in case of a file size difference. Does not verify sha differences.
@Test(timeout = 5000)
public void testDAGWithConflictingResource() {
- DAG dag = DAG.create("dag");
+ DAG dag = DAG.create("DAG-testDAGWithConflictingResource");
Map localResourceMap = new HashMap<>();
String commonResourceKey = "local resource";
localResourceMap.put("lr", LocalResource.newInstance(null, LocalResourceType.FILE,
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/TestDagTypeConverters.java b/tez-api/src/test/java/org/apache/tez/dag/api/TestDagTypeConverters.java
index 265fce9d43..edb7fd8445 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/TestDagTypeConverters.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/TestDagTypeConverters.java
@@ -34,8 +34,10 @@
import org.apache.tez.common.TezCommonUtils;
import org.apache.tez.common.security.DAGAccessControls;
import org.apache.tez.dag.api.Vertex.VertexExecutionContext;
+import org.apache.tez.dag.api.client.StatusGetOpts;
import org.apache.tez.dag.api.records.DAGProtos.ACLInfo;
import org.apache.tez.dag.api.records.DAGProtos.AMPluginDescriptorProto;
+import org.apache.tez.dag.api.records.DAGProtos.StatusGetOptsProto;
import org.apache.tez.dag.api.records.DAGProtos.TezEntityDescriptorProto;
import org.apache.tez.dag.api.records.DAGProtos.TezNamedEntityDescriptorProto;
import org.apache.tez.dag.api.records.DAGProtos.VertexExecutionContextProto;
@@ -235,6 +237,23 @@ public void testAclConversions() {
assertSame(DagTypeConverters.convertDAGAccessControlsFromProto(aclInfo), aclInfo);
}
+ /*
+ * This unit test can catch if a StatusGetOpts <-> StatusGetOptsProto value is not defined at any
+ * side.
+ */
+ @Test
+ public void testConvertStatusGetOptsToProtoCoverage() {
+ StatusGetOpts[] opts = StatusGetOpts.values();
+ for (StatusGetOpts opt : opts) {
+ DagTypeConverters.convertStatusGetOptsToProto(opt);
+ }
+
+ StatusGetOptsProto[] optProtos = StatusGetOptsProto.values();
+ for (StatusGetOptsProto proto : optProtos) {
+ DagTypeConverters.convertStatusGetOptsFromProto(proto);
+ }
+ }
+
private void assertSame(DAGAccessControls dagAccessControls, ACLInfo aclInfo) {
assertEquals(dagAccessControls.getUsersWithViewACLs(),
Sets.newHashSet(aclInfo.getUsersWithViewAccessList()));
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/TestEntityDescriptor.java b/tez-api/src/test/java/org/apache/tez/dag/api/TestEntityDescriptor.java
index 1e8a99db99..82c22ad4ef 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/TestEntityDescriptor.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/TestEntityDescriptor.java
@@ -26,38 +26,76 @@
import org.apache.commons.lang.RandomStringUtils;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.io.DataOutputBuffer;
import org.apache.tez.common.TezUtils;
import org.junit.Assert;
import org.junit.Test;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
public class TestEntityDescriptor {
- @Test
+ public void verifyResults(InputDescriptor entityDescriptor, InputDescriptor deserialized, UserPayload payload,
+ String confVal) throws IOException {
+ Assert.assertEquals(entityDescriptor.getClassName(), deserialized.getClassName());
+ // History text is not serialized when sending to tasks
+ Assert.assertNull(deserialized.getHistoryText());
+ Assert.assertArrayEquals(payload.deepCopyAsArray(), deserialized.getUserPayload().deepCopyAsArray());
+ Configuration deserializedConf = TezUtils.createConfFromUserPayload(deserialized.getUserPayload());
+ Assert.assertEquals(confVal, deserializedConf.get("testKey"));
+ }
+
+ public void testSingularWrite(InputDescriptor entityDescriptor, InputDescriptor deserialized, UserPayload payload,
+ String confVal) throws IOException {
+ DataOutputBuffer out = new DataOutputBuffer();
+ entityDescriptor.write(out);
+ out.close();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(out.getData().length);
+ bos.write(out.getData());
+
+ verify(entityDescriptor).writeSingular(eq(out), any());
+ deserialized.readFields(new DataInputStream(new ByteArrayInputStream(bos.toByteArray())));
+ verifyResults(entityDescriptor, deserialized, payload, confVal);
+ }
+
+ public void testSegmentedWrite(InputDescriptor entityDescriptor, InputDescriptor deserialized, UserPayload payload,
+ String confVal) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bos);
+ entityDescriptor.write(out);
+ out.close();
+
+ verify(entityDescriptor).writeSegmented(eq(out), any());
+ deserialized.readFields(new DataInputStream(new ByteArrayInputStream(bos.toByteArray())));
+ verifyResults(entityDescriptor, deserialized, payload, confVal);
+ }
+
+ @Test (timeout=3000)
public void testEntityDescriptorHadoopSerialization() throws IOException {
- // This tests the alternate serialization code path
- // if the DataOutput is not DataOutputBuffer
+ /* This tests the alternate serialization code path
+ * if the DataOutput is not DataOutputBuffer
+ * AND, if it indeed is, with a read/write payload */
Configuration conf = new Configuration(true);
String confVal = RandomStringUtils.random(10000, true, true);
conf.set("testKey", confVal);
UserPayload payload = TezUtils.createUserPayloadFromConf(conf);
+
+ InputDescriptor deserialized = InputDescriptor.create("dummy");
InputDescriptor entityDescriptor =
InputDescriptor.create("inputClazz").setUserPayload(payload)
- .setHistoryText("Bar123");
+ .setHistoryText("Bar123");
+ InputDescriptor entityDescriptorLivingInFear = spy(entityDescriptor);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- DataOutputStream out = new DataOutputStream(bos);
- entityDescriptor.write(out);
- out.close();
+ testSingularWrite(entityDescriptorLivingInFear, deserialized, payload, confVal);
- InputDescriptor deserialized = InputDescriptor.create("dummy");
- deserialized.readFields(new DataInputStream(new ByteArrayInputStream(bos.toByteArray())));
-
- Assert.assertEquals(entityDescriptor.getClassName(), deserialized.getClassName());
- // History text is not serialized when sending to tasks
- Assert.assertNull(deserialized.getHistoryText());
- Assert.assertArrayEquals(payload.deepCopyAsArray(), deserialized.getUserPayload().deepCopyAsArray());
- Configuration deserializedConf = TezUtils.createConfFromUserPayload(deserialized.getUserPayload());
- Assert.assertEquals(confVal, deserializedConf.get("testKey"));
+ /* make read-only payload */
+ payload = UserPayload.create(payload.getPayload());
+ entityDescriptor = InputDescriptor.create("inputClazz").setUserPayload(payload)
+ .setHistoryText("Bar123");
+ entityDescriptorLivingInFear = spy(entityDescriptor);
+ testSegmentedWrite(entityDescriptorLivingInFear, deserialized, payload, confVal);
}
-
}
diff --git a/tez-api/src/test/java/org/apache/tez/dag/api/client/rpc/TestDAGClient.java b/tez-api/src/test/java/org/apache/tez/dag/api/client/rpc/TestDAGClient.java
index 70ee1d495d..8d52aaf3b9 100644
--- a/tez-api/src/test/java/org/apache/tez/dag/api/client/rpc/TestDAGClient.java
+++ b/tez-api/src/test/java/org/apache/tez/dag/api/client/rpc/TestDAGClient.java
@@ -20,32 +20,43 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import javax.annotation.Nullable;
+
+import java.io.File;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.util.EnumSet;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.tez.client.FrameworkClient;
+import org.apache.tez.common.CachedEntity;
+import org.apache.tez.dag.api.NoCurrentDAGException;
import org.apache.tez.dag.api.TezConfiguration;
import org.apache.tez.dag.api.TezException;
import org.apache.tez.dag.api.client.DAGClient;
import org.apache.tez.dag.api.client.DAGClientImpl;
import org.apache.tez.dag.api.client.DAGClientTimelineImpl;
import org.apache.tez.dag.api.client.DAGStatus;
+import org.apache.tez.dag.api.client.DAGStatus.State;
import org.apache.tez.dag.api.client.DagStatusSource;
import org.apache.tez.dag.api.client.StatusGetOpts;
import org.apache.tez.dag.api.client.VertexStatus;
+import org.apache.tez.dag.api.client.TimelineReaderFactory.TimelineReaderStrategy;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetDAGStatusRequestProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetDAGStatusResponseProto;
import org.apache.tez.dag.api.client.rpc.DAGClientAMProtocolRPC.GetVertexStatusRequestProto;
@@ -62,6 +73,7 @@
import org.apache.tez.dag.api.records.DAGProtos.TezCountersProto;
import org.apache.tez.dag.api.records.DAGProtos.VertexStatusProto;
import org.apache.tez.dag.api.records.DAGProtos.VertexStatusStateProto;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -146,6 +158,7 @@ private void setUpData(){
.build();
vertexStatusProtoWithoutCounters = VertexStatusProto.newBuilder()
+ .setId("vertex_1")
.addDiagnostics("V_Diagnostics_0")
.setProgress(vertexProgressProto)
.setState(VertexStatusStateProto.VERTEX_SUCCEEDED) // make sure the waitForCompletion be able to finish
@@ -154,30 +167,22 @@ private void setUpData(){
.setVertexCounters(vertexCountersProto)
.build();
}
-
- private static class DAGCounterRequestMatcher extends ArgumentMatcher{
+
+ private static class DAGCounterRequestMatcher implements ArgumentMatcher{
@Override
- public boolean matches(Object argument) {
- if (argument instanceof GetDAGStatusRequestProto){
- GetDAGStatusRequestProto requestProto = (GetDAGStatusRequestProto)argument;
- return requestProto.getStatusOptionsCount() != 0
- && requestProto.getStatusOptionsList().get(0) == StatusGetOptsProto.GET_COUNTERS;
- }
- return false;
+ public boolean matches(GetDAGStatusRequestProto requestProto) {
+ return requestProto != null && requestProto.getStatusOptionsCount() != 0
+ && requestProto.getStatusOptionsList().get(0) == StatusGetOptsProto.GET_COUNTERS;
}
}
-
- private static class VertexCounterRequestMatcher extends ArgumentMatcher{
+
+ private static class VertexCounterRequestMatcher implements ArgumentMatcher{
@Override
- public boolean matches(Object argument) {
- if (argument instanceof GetVertexStatusRequestProto){
- GetVertexStatusRequestProto requestProto = (GetVertexStatusRequestProto)argument;
- return requestProto.getStatusOptionsCount() != 0
- && requestProto.getStatusOptionsList().get(0) == StatusGetOptsProto.GET_COUNTERS;
- }
- return false;
+ public boolean matches(GetVertexStatusRequestProto requestProto) {
+ return requestProto != null && requestProto.getStatusOptionsCount() != 0
+ && requestProto.getStatusOptionsList().get(0) == StatusGetOptsProto.GET_COUNTERS;
}
}
@@ -192,19 +197,19 @@ public void setUp() throws YarnException, IOException, TezException, ServiceExce
dagIdStr = "dag_9999_0001_1";
mockProxy = mock(DAGClientAMProtocolBlockingPB.class);
// return the response with Counters is the request match the CounterMatcher
- when(mockProxy.getDAGStatus(isNull(RpcController.class), any(GetDAGStatusRequestProto.class)))
+ when(mockProxy.getDAGStatus(isNull(), any()))
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(dagStatusProtoWithoutCounters).build());
- when(mockProxy.getDAGStatus(isNull(RpcController.class), argThat(new DAGCounterRequestMatcher())))
+ when(mockProxy.getDAGStatus(isNull(), argThat(new DAGCounterRequestMatcher())))
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(dagStatusProtoWithCounters).build());
- when(mockProxy.getVertexStatus(isNull(RpcController.class), any(GetVertexStatusRequestProto.class)))
+ when(mockProxy.getVertexStatus(isNull(), any()))
.thenReturn(GetVertexStatusResponseProto.newBuilder().setVertexStatus(vertexStatusProtoWithoutCounters).build());
- when(mockProxy.getVertexStatus(isNull(RpcController.class), argThat(new VertexCounterRequestMatcher())))
+ when(mockProxy.getVertexStatus(isNull(), argThat(new VertexCounterRequestMatcher())))
.thenReturn(GetVertexStatusResponseProto.newBuilder().setVertexStatus(vertexStatusProtoWithCounters).build());
TezConfiguration tezConf = new TezConfiguration();
- YarnConfiguration yarnConf = new YarnConfiguration(tezConf);
- dagClient = new DAGClientImpl(mockAppId, dagIdStr, tezConf, yarnConf, null);
+ dagClient = new DAGClientImpl(mockAppId, dagIdStr, tezConf, null,
+ UserGroupInformation.getCurrentUser());
DAGClientRPCImpl realClient = (DAGClientRPCImpl)((DAGClientImpl)dagClient).getRealClient();
realClient.appReport = mockAppReport;
realClient.proxy = mockProxy;
@@ -260,7 +265,7 @@ public void testTryKillDAG() throws Exception{
@Test(timeout = 5000)
public void testWaitForCompletion() throws Exception{
// first time return DAG_RUNNING, second time return DAG_SUCCEEDED
- when(mockProxy.getDAGStatus(isNull(RpcController.class), any(GetDAGStatusRequestProto.class)))
+ when(mockProxy.getDAGStatus(isNull(), any()))
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(dagStatusProtoWithoutCounters)
.build())
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus
@@ -281,7 +286,7 @@ public void testWaitForCompletion() throws Exception{
public void testWaitForCompletionWithStatusUpdates() throws Exception{
// first time and second time return DAG_RUNNING, third time return DAG_SUCCEEDED
- when(mockProxy.getDAGStatus(isNull(RpcController.class), any(GetDAGStatusRequestProto.class)))
+ when(mockProxy.getDAGStatus(isNull(), any()))
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(
DAGStatusProto.newBuilder(dagStatusProtoWithCounters)
.setState(DAGStatusStateProto.DAG_RUNNING).build()).build())
@@ -307,7 +312,7 @@ public void testWaitForCompletionWithStatusUpdates() throws Exception{
verify(mockProxy, times(4))
.getDAGStatus(rpcControllerArgumentCaptor.capture(), argumentCaptor.capture());
- when(mockProxy.getDAGStatus(isNull(RpcController.class), any(GetDAGStatusRequestProto.class)))
+ when(mockProxy.getDAGStatus(isNull(), any()))
.thenReturn(GetDAGStatusResponseProto.newBuilder().setDagStatus(
DAGStatusProto.newBuilder(dagStatusProtoWithCounters)
.setState(DAGStatusStateProto.DAG_RUNNING).build()).build())
@@ -340,17 +345,14 @@ public void testGetDagStatusWithTimeout() throws Exception {
TezConfiguration tezConf = new TezConfiguration();
tezConf.setLong(TezConfiguration.TEZ_DAG_STATUS_POLLINTERVAL_MS, 800l);
- YarnConfiguration yarnConf = new YarnConfiguration(tezConf);
- DAGClientImplForTest dagClient = new DAGClientImplForTest(mockAppId, dagIdStr, tezConf,
- yarnConf,null);
+ DAGClientImplForTest dagClient = new DAGClientImplForTest(mockAppId, dagIdStr, tezConf, null);
DAGClientRPCImplForTest dagClientRpc =
new DAGClientRPCImplForTest(mockAppId, dagIdStr, tezConf, null);
dagClient.setRealClient(dagClientRpc);
DAGStatus dagStatus;
-
// Fetch from RM. AM not up yet.
dagClientRpc.setAMProxy(null);
DAGStatus rmDagStatus =
@@ -370,7 +372,7 @@ public void testGetDagStatusWithTimeout() throws Exception {
// Fetch from AM. RUNNING
dagClient.resetCounters();
- dagClientRpc.resetCountesr();
+ dagClientRpc.resetCounters();
rmDagStatus =
new DAGStatus(constructDagStatusProto(DAGStatusStateProto.DAG_RUNNING), DagStatusSource.RM);
dagClient.setRmDagStatus(rmDagStatus);
@@ -390,7 +392,7 @@ public void testGetDagStatusWithTimeout() throws Exception {
// Fetch from AM. Success.
dagClient.resetCounters();
- dagClientRpc.resetCountesr();
+ dagClientRpc.resetCounters();
rmDagStatus =
new DAGStatus(constructDagStatusProto(DAGStatusStateProto.DAG_RUNNING), DagStatusSource.RM);
dagClient.setRmDagStatus(rmDagStatus);
@@ -410,7 +412,7 @@ public void testGetDagStatusWithTimeout() throws Exception {
}
@Test(timeout = 5000)
- public void testDagClientTimelineEnabledCondition() {
+ public void testDagClientTimelineEnabledCondition() throws IOException {
String historyLoggingClass = "org.apache.tez.dag.history.logging.ats.ATSHistoryLoggingService";
testAtsEnabled(mockAppId, dagIdStr, false, "", true, true);
@@ -422,34 +424,33 @@ public void testDagClientTimelineEnabledCondition() {
private static void testAtsEnabled(ApplicationId appId, String dagIdStr, boolean expected,
String loggingClass, boolean amHistoryLoggingEnabled,
- boolean dagHistoryLoggingEnabled) {
+ boolean dagHistoryLoggingEnabled) throws IOException {
TezConfiguration tezConf = new TezConfiguration();
- YarnConfiguration yarnConf = new YarnConfiguration(tezConf);
tezConf.set(TezConfiguration.TEZ_HISTORY_LOGGING_SERVICE_CLASS, loggingClass);
tezConf.setBoolean(TezConfiguration.TEZ_AM_HISTORY_LOGGING_ENABLED, amHistoryLoggingEnabled);
tezConf.setBoolean(TezConfiguration.TEZ_DAG_HISTORY_LOGGING_ENABLED, dagHistoryLoggingEnabled);
- DAGClientImplForTest dagClient = new DAGClientImplForTest(appId, dagIdStr, tezConf,
- yarnConf,null);
+ DAGClientImplForTest dagClient = new DAGClientImplForTest(appId, dagIdStr, tezConf, null);
assertEquals(expected, dagClient.getIsATSEnabled());
}
private static class DAGClientRPCImplForTest extends DAGClientRPCImpl {
-
+ private AtomicReference faultAMInjectedRef;
int numGetStatusViaAmInvocations = 0;
public DAGClientRPCImplForTest(ApplicationId appId, String dagId,
TezConfiguration conf,
- @Nullable FrameworkClient frameworkClient) {
- super(appId, dagId, conf, frameworkClient);
+ @Nullable FrameworkClient frameworkClient) throws IOException {
+ super(appId, dagId, conf, frameworkClient, UserGroupInformation.getCurrentUser());
+ faultAMInjectedRef = new AtomicReference<>(null);
}
void setAMProxy(DAGClientAMProtocolBlockingPB proxy) {
this.proxy = proxy;
}
- void resetCountesr() {
+ void resetCounters() {
numGetStatusViaAmInvocations = 0;
}
@@ -466,19 +467,25 @@ boolean createAMProxyIfNeeded() throws IOException, TezException {
DAGStatus getDAGStatusViaAM(Set statusOptions, long timeout)
throws IOException, TezException {
numGetStatusViaAmInvocations++;
+ if (faultAMInjectedRef.get() != null) {
+ throw faultAMInjectedRef.get();
+ }
return super.getDAGStatusViaAM(statusOptions, timeout);
}
+
+ void injectAMFault(TezException exception) {
+ faultAMInjectedRef.set(exception);
+ }
}
private static class DAGClientImplForTest extends DAGClientImpl {
private DAGStatus rmDagStatus;
int numGetStatusViaRmInvocations = 0;
-
+ private volatile boolean faultInjected;
public DAGClientImplForTest(ApplicationId appId, String dagId, TezConfiguration conf,
- YarnConfiguration yarnConf,
- @Nullable FrameworkClient frameworkClient) {
- super(appId, dagId, conf, yarnConf, frameworkClient);
+ @Nullable FrameworkClient frameworkClient) throws IOException {
+ super(appId, dagId, conf, frameworkClient, UserGroupInformation.getCurrentUser());
}
private void setRealClient(DAGClientRPCImplForTest dagClientRpcImplForTest) {
@@ -496,6 +503,9 @@ void resetCounters() {
@Override
protected DAGStatus getDAGStatusViaRM() throws TezException, IOException {
numGetStatusViaRmInvocations++;
+ if (faultInjected) {
+ throw new IOException("Fault Injected for RM");
+ }
return rmDagStatus;
}
@@ -503,6 +513,18 @@ public boolean getIsATSEnabled() {
return isATSEnabled;
}
+ void injectFault() {
+ faultInjected = true;
+ }
+
+ DAGStatus getCachedDAGStatus() {
+ CachedEntity cacheRef = getCachedDAGStatusRef();
+ return cacheRef.getValue();
+ }
+
+ void enforceExpirationCachedDAGStatus() {
+ getCachedDAGStatusRef().enforceExpiration();
+ }
}
private DAGProtos.DAGStatusProto.Builder constructDagStatusProto(DAGStatusStateProto stateProto) {
@@ -516,7 +538,7 @@ private DAGClientAMProtocolBlockingPB createMockProxy(final DAGStatusStateProto
ServiceException {
DAGClientAMProtocolBlockingPB mock = mock(DAGClientAMProtocolBlockingPB.class);
- doAnswer(new Answer() {
+ doAnswer(new Answer