org.bouncycastle
bcprov-jdk16
test
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/BoundedAppender.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/BoundedAppender.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ad595f594e3477f55330f3e5529c6af05cf7856
--- /dev/null
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/BoundedAppender.java
@@ -0,0 +1,266 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.util;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import javax.annotation.concurrent.NotThreadSafe;
+import java.io.Serializable;
+import java.util.Queue;
+
+/**
+ * An {@link Appendable} implementation that considers its {@link #limit} as
+ * upper bound. While {@link #append(CharSequence) append}ing the lengths of the
+ * past input values are gathered in a {@link Queue queue}.
+ *
+ * When {@link #limit} would be reached on append, if possible, at head of
+ * {@link #pastInputValues past input values}, some of the {@link String}s are
+ * {@link StringBuilder#delete(int, int) delete}d first considering:
+ *
+ * - oldest message is truncated / deleted first (FIFO)
+ * - parts of the last message can also be truncated from the message head,
+ * not just whole messages / lines
+ * - when there was as least truncate / delete necessary, keep the last
+ * characters fitting into {@link #limit} of the message, or of the previous
+ * message that once fit but another message was {@link #append(CharSequence)
+ * append}ed
+ * - last message is truncated from its head, keeping last chars
+ * - ellipses at the head of the last message truncated
+ *
+ *
+ * An example:
+ *
+ *
+ * {
+ * @code
+ * // At the beginning it's an empty string
+ * final Appendable shortAppender = new BoundedAppender(80);
+ * // The whole message fits into limit
+ * shortAppender.append(
+ * "message1 this is a very long message but fitting into limit\n");
+ * // The first message is truncated, the second not
+ * shortAppender.append("message2 this is shorter than the previous one\n");
+ * // The first message is deleted, the second truncated, the third preserved
+ * shortAppender.append("message3 this is even shorter message, maybe.\n");
+ * // The first two are deleted, the third one truncated, the last preserved
+ * shortAppender.append("message4 the shortest one, yet the greatest :)");
+ * // Current contents are like this:
+ * // Diagnostic messages truncated, showing last (80) chars out of (199) in
+ * // total:
+ * // ...s is even shorter message, maybe.
+ * // message4 the shortest one, yet the greatest :)
+ * }
+ *
+ *
+ * Note that null values are {@link #append(CharSequence) append}ed
+ * just like in {@link StringBuilder#append(CharSequence) original
+ * implementation}.
+ *
+ * Note that this class is not thread safe.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+@NotThreadSafe
+public class BoundedAppender implements Appendable, Serializable, CharSequence {
+ private static final long serialVersionUID = 1L;
+ @VisibleForTesting
+ static final String TRUNCATED_MESSAGES_TEMPLATE =
+ "Diagnostic messages truncated, showing last "
+ + "(%d) chars out of (%d) in total:\n...%s";
+
+ private final int limit;
+ private int totalInputLength = 0;
+ private final StringBuilder pastInputValues = new StringBuilder();
+
+ /**
+ * Constructor to initialize to any {@link #limit}.
+ *
+ * @param limit upper bound of the character count
+ */
+ public BoundedAppender(final int limit) {
+ Preconditions.checkArgument(limit > 0, "limit should be positive");
+
+ this.limit = limit;
+ }
+
+ /**
+ * Appends the specified string to this BoundedAppender, considering
+ * {@link #limit} as upper bound in a way that former {@code append}ed whole
+ * strings are {@link StringBuilder#delete(int, int) delete}d in FIFO order.
+ *
+ * If {@code csq} is {@code null}, then the four characters {@code "null"} are
+ * appended.
+ *
+ * @param csq the {@link CharSequence} to be appended
+ * @return {@code this}
+ * @throws IllegalArgumentException if {@code csq} doesn't fit into
+ * {@code limit}
+ * @see Appendable#append(CharSequence)
+ */
+ @Override
+ public BoundedAppender append(CharSequence csq) {
+ csq = ensureNotNull(csq);
+
+ return append(csq, 0, csq.length());
+ }
+
+ /**
+ * Appends the specified string to this BoundedAppender, considering
+ * {@link #limit} as upper bound in a way that former {@code append}ed whole
+ * strings are {@link StringBuilder#delete(int, int) delete}d in FIFO order.
+ *
+ * If {@code csq} is {@code null}, then the four characters {@code "null"} are
+ * considered for appending.
+ *
+ * {@code start} and {@code end} indexes are applied to {@code csq} in the
+ * general meaning of {@see CharSequence#subSequence(start, end)}, with the
+ * only exception that we do not allow empty subsequences to be appended:
+ * {@code start < end} should be held in all circumstances.
+ *
+ * @param csq The character sequence from which a subsequence will be
+ * appended. If csq is null, then characters will
+ * be appended as if csq contained the four characters
+ * "null".
+ * @param start The index of the first character in the subsequence
+ * @param end end index, excluded
+ * @return {@code this}
+ * @throws IllegalArgumentException if {@code csq} doesn't fit into
+ * {@code limit}, or {@code end} is not more than {@code start}
+ * @throws IndexOutOfBoundsException if start or end are
+ * negative, start is greater than end, or
+ * end is greater than csq.length()
+ * @see Appendable#append(CharSequence, int, int)
+ */
+ @Override
+ public BoundedAppender append(CharSequence csq, final int start,
+ final int end) {
+ csq = ensureNotNull(csq);
+
+ final int inputLength = end - start;
+ Preconditions.checkPositionIndexes(start, end, csq.length());
+ Preconditions.checkElementIndex(end - 1, csq.length());
+ Preconditions.checkState(start < end, String
+ .format("end index (%d) must be before start index (%d)", end, start));
+
+ csq = checkAndCut(csq, start, end);
+ pastInputValues.append(csq);
+ totalInputLength += inputLength;
+
+ return this;
+ }
+
+ /**
+ * Appends the specified character to this BoundedAppender.
+ *
+ * @param c the character to append
+ * @return {@code this}
+ */
+ @Override
+ public BoundedAppender append(final char c) {
+ return append(String.valueOf(c));
+ }
+
+ private CharSequence ensureNotNull(final CharSequence csq) {
+ if (csq == null) {
+ return "null";
+ }
+
+ return csq;
+ }
+
+ private CharSequence checkAndCut(CharSequence csq, final int start, int end) {
+ final int inputLength = end - start;
+ if (shouldCutNew(inputLength)) {
+ csq = cutNew(csq, end);
+ cutPastAll();
+ } else if (shouldCutPast(inputLength)) {
+ csq = csq.subSequence(start, end);
+ cutPastBy(lengthToCutPast(inputLength));
+ } else {
+ csq = csq.subSequence(start, end);
+ }
+
+ return csq;
+ }
+
+ private boolean shouldCutNew(final int inputLength) {
+ return inputLength > limit;
+ }
+
+ private CharSequence cutNew(final CharSequence csq, final int end) {
+ final int newStart = end - limit;
+
+ Preconditions.checkElementIndex(newStart, csq.length(),
+ String.format("new start index (%d) should be withing length (%d)",
+ newStart, csq.length()));
+
+ return csq.subSequence(newStart, end);
+ }
+
+ private void cutPastAll() {
+ pastInputValues.delete(0, pastInputValues.length());
+ }
+
+ private boolean shouldCutPast(final int newInputLength) {
+ return lengthToCutPast(newInputLength) > 0;
+ }
+
+ private int lengthToCutPast(final int newInputLength) {
+ return pastInputValues.length() + newInputLength - limit;
+ }
+
+ private void cutPastBy(final int cutLength) {
+ Preconditions.checkArgument(cutLength > 0, "nothing to cut");
+ Preconditions.checkState(pastInputValues.length() >= cutLength,
+ String.format("cannot cut %d, could cut at most %d",
+ pastInputValues.length(), cutLength));
+
+ pastInputValues.delete(0, cutLength);
+ }
+
+ @Override
+ public int length() {
+ return pastInputValues.length();
+ }
+
+ @Override
+ public char charAt(final int index) {
+ return pastInputValues.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(final int start, final int end) {
+ return pastInputValues.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ if (totalInputLength > pastInputValues.length()) {
+ final String truncatedMessages =
+ String.format(TRUNCATED_MESSAGES_TEMPLATE, pastInputValues.length(),
+ totalInputLength, pastInputValues.toString());
+ return truncatedMessages;
+ }
+
+ return pastInputValues.toString();
+ }
+}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
index 1e929a8c5007e12d9d8c428880d33ea0e40390bf..68f370f5bf86f5f79d45e00a5cf282b69396b999 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
@@ -3014,4 +3014,19 @@
3000
+
+
+ Defines the capacity of the diagnostics message of an application
+ attempt, in kilobytes.
+ When using ZooKeeper to store application state behavior, it's
+ important to limit the size of the diagnostic messages to
+ prevent YARN from overwhelming ZooKeeper. In cases where
+ yarn.resourcemanager.state-store.max-completed-applications is set to
+ a large number, it may be desirable to reduce the value of this property
+ to limit the total data stored.
+
+ yarn.app.attempt.diagnostics.capacity.kb
+ 64
+
+
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/BoundedAppenderTest.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/BoundedAppenderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..607cadfd4f3bd90c97b468357c511691aae16db6
--- /dev/null
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/BoundedAppenderTest.java
@@ -0,0 +1,206 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.util;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing {@link BoundedAppender} behavior.
+ */
+public class BoundedAppenderTest {
+ @Rule
+ public ExpectedException expected = ExpectedException.none();
+
+ @Test
+ public void initWithZeroLimitThrowsException() {
+ expected.expect(IllegalArgumentException.class);
+ expected.expectMessage("limit should be positive");
+
+ new BoundedAppender(0);
+ }
+
+ @Test
+ public void nothingAppendedNothingRead() {
+ final BoundedAppender boundedAppender = new BoundedAppender(1);
+
+ assertEquals("nothing appended, nothing read", "",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void nullAppendedNullStringRead() {
+ final BoundedAppender boundedAppender = new BoundedAppender(4);
+ boundedAppender.append(null);
+
+ assertEquals("null appended, \"null\" read", "null",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendLastAboveLimitPreservesLastMessagePostfix() {
+ final BoundedAppender boundedAppender = new BoundedAppender(3);
+
+ boundedAppender.append("ab");
+ boundedAppender.append("cde");
+ boundedAppender.append("fghij");
+
+ assertEquals(
+ "last value appended above limit postfix is read correctly", String
+ .format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 10, "hij"),
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendMiddleAboveLimitPreservesLastMessageAndMiddlePostfix() {
+ final BoundedAppender boundedAppender = new BoundedAppender(3);
+
+ boundedAppender.append("ab");
+ boundedAppender.append("cde");
+
+ assertEquals("last value appended above limit postfix is read correctly",
+ String.format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 5, "cde"),
+ boundedAppender.toString());
+
+ boundedAppender.append("fg");
+
+ assertEquals(
+ "middle value appended above limit postfix and last value are "
+ + "read correctly",
+ String.format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 7, "efg"),
+ boundedAppender.toString());
+
+ boundedAppender.append("hijkl");
+
+ assertEquals(
+ "last value appended above limit postfix is read correctly", String
+ .format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 12, "jkl"),
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendBelowLimitOnceValueIsReadCorrectly() {
+ final BoundedAppender boundedAppender = new BoundedAppender(2);
+
+ boundedAppender.append("ab");
+
+ assertEquals("value appended is read correctly", "ab",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendValuesBelowLimitAreReadCorrectlyInFifoOrder() {
+ final BoundedAppender boundedAppender = new BoundedAppender(3);
+
+ boundedAppender.append("ab");
+ boundedAppender.append("cd");
+ boundedAppender.append("e");
+ boundedAppender.append("fg");
+
+ assertEquals("last values appended fitting limit are read correctly",
+ String.format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 7, "efg"),
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendValuesWithInvalidIndicesThrowsException() {
+ final BoundedAppender boundedAppender = new BoundedAppender(1);
+
+ expected.expect(IndexOutOfBoundsException.class);
+
+ boundedAppender.append("a", -1, 0);
+
+ expected.expect(IllegalStateException.class);
+
+ boundedAppender.append("a", 0, 0);
+
+ expected.expect(IndexOutOfBoundsException.class);
+
+ boundedAppender.append("a", 0, 2);
+
+ expected.expect(IndexOutOfBoundsException.class);
+
+ boundedAppender.append("a", 1, 1);
+ }
+
+ @Test
+ public void nullAppendedWithValidIndicesNullRead() {
+ final BoundedAppender boundedAppender = new BoundedAppender(4);
+
+ boundedAppender.append(null, 0, 4);
+
+ assertEquals("null appended with valid indices, \"null\" read", "null",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendValueWithValidIndicesIsReadCorrectly() {
+ final BoundedAppender boundedAppender = new BoundedAppender(2);
+
+ boundedAppender.append("abcd", 1, 3);
+
+ assertEquals("value appended with valid indices is read correctly", "bc",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendValuesWithValidIndicesAreReadCorrectlyInFifoOrder() {
+ final BoundedAppender boundedAppender = new BoundedAppender(3);
+
+ boundedAppender.append("abcd", 1, 3);
+ boundedAppender.append("efgh", 0, 2);
+ boundedAppender.append("i", 0, 1);
+ boundedAppender.append("jk", 0, 2);
+
+ assertEquals(
+ "last values appended with valid parameters fitting limit are "
+ + "read correctly",
+ String.format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 3, 7, "ijk"),
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendOneCharIsReadCorrectly() {
+ final BoundedAppender boundedAppender = new BoundedAppender(1);
+
+ boundedAppender.append('a');
+
+ assertEquals("one char appended is read correctly", "a",
+ boundedAppender.toString());
+ }
+
+ @Test
+ public void appendMultipleCharsAreReadCorrectlyInFifoOrder() {
+ final BoundedAppender boundedAppender = new BoundedAppender(2);
+
+ boundedAppender.append('a');
+ boundedAppender.append('b');
+ boundedAppender.append('c');
+ boundedAppender.append('d');
+
+ assertEquals(
+ "multiple chars appended are read correctly, the ones deleted in "
+ + "FIFO order",
+ String.format(BoundedAppender.TRUNCATED_MESSAGES_TEMPLATE, 2, 4, "cd"),
+ boundedAppender.toString());
+ }
+}
\ No newline at end of file
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
index ab84985edcbc2a6ee34de90ec9de2c1edfbfcf1d..279854ddaebe88c69eb1c9c5dcb2002d307afe81 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java
@@ -109,6 +109,7 @@
import org.apache.hadoop.yarn.state.SingleArcTransition;
import org.apache.hadoop.yarn.state.StateMachine;
import org.apache.hadoop.yarn.state.StateMachineFactory;
+import org.apache.hadoop.yarn.util.BoundedAppender;
import org.apache.hadoop.yarn.webapp.util.WebAppUtils;
import com.google.common.annotations.VisibleForTesting;
@@ -171,7 +172,7 @@
// Set to null initially. Will eventually get set
// if an RMAppAttemptUnregistrationEvent occurs
private FinalApplicationStatus finalStatus = null;
- private final StringBuilder diagnostics = new StringBuilder();
+ private final BoundedAppender diagnostics;
private int amContainerExitStatus = ContainerExitStatus.INVALID;
private Configuration conf;
@@ -518,6 +519,42 @@ public RMAppAttemptImpl(ApplicationAttemptId appAttemptId,
this.amReq = amReq;
this.blacklistedNodesForAM = amBlacklistManager;
+
+ final int diagnosticsLimitKB = getDiagnosticsLimitKBOrThrow(conf);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(YarnConfiguration.APP_ATTEMPT_DIAGNOSTICS_CAPACITY_KB + " : " +
+ diagnosticsLimitKB);
+ }
+
+ this.diagnostics = new BoundedAppender(diagnosticsLimitKB * 1024);
+ }
+
+ private int getDiagnosticsLimitKBOrThrow(final Configuration configuration) {
+ try {
+ final int diagnosticsLimitKB = configuration.getInt(
+ YarnConfiguration.APP_ATTEMPT_DIAGNOSTICS_CAPACITY_KB,
+ YarnConfiguration.DEFAULT_APP_ATTEMPT_DIAGNOSTICS_CAPACITY_KB);
+
+ if (diagnosticsLimitKB <= 0) {
+ final String message =
+ YarnConfiguration.APP_ATTEMPT_DIAGNOSTICS_CAPACITY_KB + " ("
+ + diagnosticsLimitKB + ") should be positive.";
+ LOG.error(message);
+
+ throw new YarnRuntimeException(message);
+ }
+
+ return diagnosticsLimitKB;
+ } catch (final NumberFormatException nfe) {
+ final String message = String.format(
+ "%s should be a positive integer. Exception message: %s",
+ YarnConfiguration.APP_ATTEMPT_DIAGNOSTICS_CAPACITY_KB,
+ nfe.getMessage());
+ LOG.error(message);
+
+ throw new YarnRuntimeException(message);
+ }
}
@Override
@@ -926,8 +963,8 @@ public void recover(RMState state) {
attemptState.getState()));
}
- diagnostics.append("Attempt recovered after RM restart");
- diagnostics.append(attemptState.getDiagnostics());
+ appendToDiagnosticsSafely("Attempt recovered after RM restart");
+ appendToDiagnosticsSafely(attemptState.getDiagnostics());
this.amContainerExitStatus = attemptState.getAMContainerExitStatus();
if (amContainerExitStatus == ContainerExitStatus.PREEMPTED) {
this.attemptMetrics.setIsPreempted();
@@ -942,12 +979,21 @@ public void recover(RMState state) {
this.startTime = attemptState.getStartTime();
this.finishTime = attemptState.getFinishTime();
this.attemptMetrics.updateAggregateAppResourceUsage(
- attemptState.getMemorySeconds(),attemptState.getVcoreSeconds());
+ attemptState.getMemorySeconds(), attemptState.getVcoreSeconds());
this.attemptMetrics.updateAggregatePreemptedAppResourceUsage(
attemptState.getPreemptedMemorySeconds(),
attemptState.getPreemptedVcoreSeconds());
}
+ private void appendToDiagnosticsSafely(final String diagnosticsMessage) {
+ try {
+ diagnostics.append(diagnosticsMessage);
+ } catch (final IndexOutOfBoundsException | IllegalStateException e) {
+ LOG.warn("There was a problem appending a diagnostics message to an RM "
+ + "app attempt. Here is the message: %s", e);
+ }
+ }
+
public void transferStateFromAttempt(RMAppAttempt attempt) {
this.justFinishedContainers = attempt.getJustFinishedContainersReference();
this.finishedContainersSentToAM =
@@ -1463,7 +1509,7 @@ public AttemptFailedTransition() {
@Override
public void transition(RMAppAttemptImpl appAttempt, RMAppAttemptEvent event) {
if (event.getDiagnosticMsg() != null) {
- appAttempt.diagnostics.append(event.getDiagnosticMsg());
+ appAttempt.appendToDiagnosticsSafely(event.getDiagnosticMsg());
}
super.transition(appAttempt, event);
}
@@ -1566,7 +1612,7 @@ public void transition(RMAppAttemptImpl appAttempt,
RMAppAttemptEvent event) {
// Use diagnostic from launcher
- appAttempt.diagnostics.append(event.getDiagnosticMsg());
+ appAttempt.appendToDiagnosticsSafely(event.getDiagnosticMsg());
// Tell the app, scheduler
super.transition(appAttempt, event);
@@ -1655,8 +1701,7 @@ public void transition(RMAppAttemptImpl appAttempt,
private void setAMContainerCrashedDiagnosticsAndExitStatus(
RMAppAttemptContainerFinishedEvent finishEvent) {
ContainerStatus status = finishEvent.getContainerStatus();
- String diagnostics = getAMContainerCrashedDiagnostics(finishEvent);
- this.diagnostics.append(diagnostics);
+ appendToDiagnosticsSafely(getAMContainerCrashedDiagnostics(finishEvent));
this.amContainerExitStatus = status.getExitStatus();
}
@@ -1718,7 +1763,7 @@ public ExpiredTransition() {
@Override
public void transition(RMAppAttemptImpl appAttempt,
RMAppAttemptEvent event) {
- appAttempt.diagnostics.append(getAMExpiredDiagnostics(event));
+ appAttempt.appendToDiagnosticsSafely(getAMExpiredDiagnostics(event));
super.transition(appAttempt, event);
}
}
@@ -1740,7 +1785,7 @@ public UnexpectedAMRegisteredTransition() {
@Override
public void transition(RMAppAttemptImpl appAttempt, RMAppAttemptEvent event) {
assert appAttempt.submissionContext.getUnmanagedAM();
- appAttempt.diagnostics.append(getUnexpectedAMRegisteredDiagnostics());
+ appAttempt.appendToDiagnosticsSafely(getUnexpectedAMRegisteredDiagnostics());
super.transition(appAttempt, event);
}
@@ -1825,7 +1870,7 @@ private void updateInfoOnAMUnregister(RMAppAttemptEvent event) {
progress = 1.0f;
RMAppAttemptUnregistrationEvent unregisterEvent =
(RMAppAttemptUnregistrationEvent) event;
- diagnostics.append(unregisterEvent.getDiagnosticMsg());
+ appendToDiagnosticsSafely(unregisterEvent.getDiagnosticMsg());
originalTrackingUrl = sanitizeTrackingUrl(unregisterEvent.getFinalTrackingUrl());
finalStatus = unregisterEvent.getFinalApplicationStatus();
}