aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar ruperts <ruperts@google.com>2017-11-04 07:58:02 +0100
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-11-06 20:20:28 +0100
commit0510f4a7feaa1f8806cf46d151b78114d6f4f5a1 (patch)
tree74bc3f258c3879bdf294303ed8aadeff4e2131cd /src/main/java/com/google/devtools
parent02fb4bb419c7ad43b17d0cffae7787bf1fa0c676 (diff)
Add optional user execution time and system execution time fields to TerminationStatus, and also add a TerminationStatus.Builder and tests.
RELNOTES: None. PiperOrigin-RevId: 174557303
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r--src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java169
2 files changed, 154 insertions, 17 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
index c5f1657d83..af042af8d0 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunner.java
@@ -319,7 +319,7 @@ public final class LocalSpawnRunner implements SpawnRunner {
setState(State.SUCCESS);
Duration wallTime = Duration.ofMillis(System.currentTimeMillis() - startTime);
boolean wasTimeout =
- result.getTerminationStatus().timedout()
+ result.getTerminationStatus().timedOut()
|| (useProcessWrapper && wasTimeout(policy.getTimeout(), wallTime));
Status status = wasTimeout ? Status.TIMEOUT : Status.SUCCESS;
int exitCode =
diff --git a/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java b/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java
index abee00012e..4d7a1bd657 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java
@@ -14,6 +14,9 @@
package com.google.devtools.build.lib.shell;
+import java.time.Duration;
+import java.util.Optional;
+
/**
* Represents the termination status of a command. {@link Process#waitFor} is
* not very precisely specified, so this class encapsulates the interpretation
@@ -29,7 +32,10 @@ package com.google.devtools.build.lib.shell;
public final class TerminationStatus {
private final int waitResult;
- private final boolean timedout;
+ private final boolean timedOut;
+ private final Optional<Duration> wallExecutionTime;
+ private final Optional<Duration> userExecutionTime;
+ private final Optional<Duration> systemExecutionTime;
/**
* Values taken from the glibc strsignal(3) function.
@@ -79,10 +85,34 @@ public final class TerminationStatus {
* Construct a TerminationStatus instance from a Process waitFor code.
*
* @param waitResult the value returned by {@link java.lang.Process#waitFor}.
+ * @param timedOut whether the execution timed out
*/
- public TerminationStatus(int waitResult, boolean timedout) {
+ public TerminationStatus(int waitResult, boolean timedOut) {
+ this(waitResult, timedOut, Optional.empty(), Optional.empty(), Optional.empty());
+ }
+
+ /**
+ * Construct a TerminationStatus instance from a Process waitFor code.
+ *
+ * <p>TerminationStatus objects are considered equal if they have the same waitResult.
+ *
+ * @param waitResult the value returned by {@link java.lang.Process#waitFor}.
+ * @param timedOut whether the execution timed out
+ * @param wallExecutionTime the wall execution time of the command, if available
+ * @param userExecutionTime the user execution time of the command, if available
+ * @param systemExecutionTime the system execution time of the command, if available
+ */
+ public TerminationStatus(
+ int waitResult,
+ boolean timedOut,
+ Optional<Duration> wallExecutionTime,
+ Optional<Duration> userExecutionTime,
+ Optional<Duration> systemExecutionTime) {
this.waitResult = waitResult;
- this.timedout = timedout;
+ this.timedOut = timedOut;
+ this.wallExecutionTime = wallExecutionTime;
+ this.userExecutionTime = userExecutionTime;
+ this.systemExecutionTime = systemExecutionTime;
}
/**
@@ -110,14 +140,12 @@ public final class TerminationStatus {
* Returns true iff the process exited normally.
*/
public boolean exited() {
- return !timedout && (waitResult < SIGNAL_1 || waitResult > SIGNAL_63);
+ return !timedOut && (waitResult < SIGNAL_1 || waitResult > SIGNAL_63);
}
- /**
- * Returns true if the process timed out.
- */
- public boolean timedout() {
- return timedout;
+ /** Returns true if the process timed out. */
+ public boolean timedOut() {
+ return timedOut;
}
/**
@@ -135,27 +163,57 @@ public final class TerminationStatus {
* if exited() returns true.
*/
public int getTerminatingSignal() {
- if (exited() || timedout) {
+ if (exited() || timedOut) {
throw new IllegalStateException("getTerminatingSignal() not defined");
}
return waitResult - SIGNAL_1 + 1;
}
/**
+ * Returns the wall execution time.
+ *
+ * @return the measurement, or empty in case of execution errors or when the measurement is not
+ * implemented for the current platform
+ */
+ public Optional<Duration> getWallExecutionTime() {
+ return wallExecutionTime;
+ }
+
+ /**
+ * Returns the user execution time.
+ *
+ * @return the measurement, or empty in case of execution errors or when the measurement is not
+ * implemented for the current platform
+ */
+ public Optional<Duration> getUserExecutionTime() {
+ return userExecutionTime;
+ }
+
+ /**
+ * Returns the system execution time.
+ *
+ * @return the measurement, or empty in case of execution errors or when the measurement is not
+ * implemented for the current platform
+ */
+ public Optional<Duration> getSystemExecutionTime() {
+ return systemExecutionTime;
+ }
+
+ /**
* Returns a short string describing the termination status.
* e.g. "Exit 1" or "Hangup".
*/
public String toShortString() {
- return exited() ? "Exit " + getExitCode()
- : timedout ? "Timeout"
- : getSignalString(getTerminatingSignal());
+ return exited()
+ ? "Exit " + getExitCode()
+ : (timedOut ? "Timeout" : getSignalString(getTerminatingSignal()));
}
@Override
public String toString() {
if (exited()) {
return "Process exited with status " + getExitCode();
- } else if (timedout) {
+ } else if (timedOut) {
return "Timed out";
} else {
return "Process terminated by signal " + getTerminatingSignal();
@@ -169,7 +227,86 @@ public final class TerminationStatus {
@Override
public boolean equals(Object other) {
- return other instanceof TerminationStatus &&
- ((TerminationStatus) other).waitResult == this.waitResult;
+ return other instanceof TerminationStatus
+ && ((TerminationStatus) other).waitResult == this.waitResult;
+ }
+
+ /** Returns a new {@link TerminationStatus.Builder}. */
+ public static Builder builder() {
+ return new TerminationStatus.Builder();
+ }
+
+ /** Builder for {@link TerminationStatus} objects. */
+ public static class Builder {
+ // We use nullness here instead of Optional to avoid confusion between fields that may not
+ // yet have been set from fields that can legitimately hold an Optional value in the built
+ // object.
+
+ private Integer waitResponse = null;
+ private Boolean timedOut = null;
+
+ private Optional<Duration> wallExecutionTime = Optional.empty();
+ private Optional<Duration> userExecutionTime = Optional.empty();
+ private Optional<Duration> systemExecutionTime = Optional.empty();
+
+ /** Sets the value returned by {@link java.lang.Process#waitFor}. */
+ public Builder setWaitResponse(int waitResponse) {
+ this.waitResponse = waitResponse;
+ return this;
+ }
+
+ /** Sets whether the action timed out or not. */
+ public Builder setTimedOut(boolean timedOut) {
+ this.timedOut = timedOut;
+ return this;
+ }
+
+ /** Sets the wall execution time. */
+ public Builder setWallExecutionTime(Duration wallExecutionTime) {
+ this.wallExecutionTime = Optional.of(wallExecutionTime);
+ return this;
+ }
+
+ /** Sets the user execution time. */
+ public Builder setUserExecutionTime(Duration userExecutionTime) {
+ this.userExecutionTime = Optional.of(userExecutionTime);
+ return this;
+ }
+
+ /** Sets the system execution time. */
+ public Builder setSystemExecutionTime(Duration systemExecutionTime) {
+ this.systemExecutionTime = Optional.of(systemExecutionTime);
+ return this;
+ }
+
+ /** Sets or clears the wall execution time. */
+ public Builder setWallExecutionTime(Optional<Duration> wallExecutionTime) {
+ this.wallExecutionTime = wallExecutionTime;
+ return this;
+ }
+
+ /** Sets or clears the user execution time. */
+ public Builder setUserExecutionTime(Optional<Duration> userExecutionTime) {
+ this.userExecutionTime = userExecutionTime;
+ return this;
+ }
+
+ /** Sets or clears the system execution time. */
+ public Builder setSystemExecutionTime(Optional<Duration> systemExecutionTime) {
+ this.systemExecutionTime = systemExecutionTime;
+ return this;
+ }
+
+ /** Builds a {@link TerminationStatus} object. */
+ public TerminationStatus build() {
+ if (waitResponse == null) {
+ throw new IllegalStateException("waitResponse never set");
+ }
+ if (timedOut == null) {
+ throw new IllegalStateException("timedOut never set");
+ }
+ return new TerminationStatus(
+ waitResponse, timedOut, wallExecutionTime, userExecutionTime, systemExecutionTime);
+ }
}
}