| // Copyright 2017 The Bazel Authors. All rights reserved. |
| // |
| // 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 com.google.devtools.build.lib.actions; |
| |
| import static com.google.common.base.Preconditions.checkState; |
| |
| import com.google.auto.value.AutoValue; |
| import com.google.common.collect.ImmutableList; |
| import java.time.Duration; |
| import java.util.List; |
| import java.util.Optional; |
| import java.util.function.Function; |
| |
| /** Holds the result(s) of an action's execution. */ |
| @AutoValue |
| public abstract class ActionResult { |
| |
| /** An empty ActionResult used by Actions that don't have any metadata to return. */ |
| public static final ActionResult EMPTY = ActionResult.create(ImmutableList.of()); |
| |
| /** Returns the SpawnResults for the action. */ |
| public abstract List<SpawnResult> spawnResults(); |
| |
| /** Returns a builder that can be used to construct a {@link ActionResult} object. */ |
| public static Builder builder() { |
| return new AutoValue_ActionResult.Builder(); |
| } |
| |
| /** |
| * Returns the cumulative time taken by a series of {@link SpawnResult}s. |
| * |
| * @param getSpawnResultExecutionTime a selector that returns either the wall, user or system time |
| * for each {@link SpawnResult} being considered |
| * @return the cumulative time, or empty if no spawn results contained this time |
| */ |
| private Optional<Duration> getCumulativeTime( |
| Function<SpawnResult, Optional<Duration>> getSpawnResultExecutionTime) { |
| Long totalMillis = null; |
| for (SpawnResult spawnResult : spawnResults()) { |
| Optional<Duration> executionTime = getSpawnResultExecutionTime.apply(spawnResult); |
| if (executionTime.isPresent()) { |
| if (totalMillis == null) { |
| totalMillis = executionTime.get().toMillis(); |
| } else { |
| totalMillis += executionTime.get().toMillis(); |
| } |
| } |
| } |
| if (totalMillis == null) { |
| return Optional.empty(); |
| } else { |
| return Optional.of(Duration.ofMillis(totalMillis)); |
| } |
| } |
| |
| /** |
| * Returns the cumulative total of long values taken from a series of {@link SpawnResult}s. |
| * |
| * @param getSpawnResultLongValue a selector that returns a long value for each {@link |
| * SpawnResult} being considered |
| * @return the total, or empty if no spawn results contained this long value |
| */ |
| private Optional<Long> getCumulativeLong( |
| Function<SpawnResult, Optional<Long>> getSpawnResultLongValue) { |
| Long longTotal = null; |
| for (SpawnResult spawnResult : spawnResults()) { |
| Optional<Long> longValue = getSpawnResultLongValue.apply(spawnResult); |
| if (longValue.isPresent()) { |
| if (longTotal == null) { |
| longTotal = longValue.get(); |
| } else { |
| longTotal += longValue.get(); |
| } |
| } |
| } |
| if (longTotal == null) { |
| return Optional.empty(); |
| } else { |
| return Optional.of(longTotal); |
| } |
| } |
| |
| /** |
| * Returns the cumulative command execution wall time for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Duration> cumulativeCommandExecutionWallTime() { |
| return getCumulativeTime(spawnResult -> spawnResult.getWallTime()); |
| } |
| |
| /** |
| * Returns the cumulative command execution user time for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Duration> cumulativeCommandExecutionUserTime() { |
| return getCumulativeTime(spawnResult -> spawnResult.getUserTime()); |
| } |
| |
| /** |
| * Returns the cumulative command execution system time for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Duration> cumulativeCommandExecutionSystemTime() { |
| return getCumulativeTime(spawnResult -> spawnResult.getSystemTime()); |
| } |
| |
| /** |
| * Returns the cumulative number of block input operations for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Long> cumulativeCommandExecutionBlockInputOperations() { |
| return getCumulativeLong(spawnResult -> spawnResult.getNumBlockInputOperations()); |
| } |
| |
| /** |
| * Returns the cumulative number of block output operations for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Long> cumulativeCommandExecutionBlockOutputOperations() { |
| return getCumulativeLong(spawnResult -> spawnResult.getNumBlockOutputOperations()); |
| } |
| |
| /** |
| * Returns the cumulative number of involuntary context switches for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Long> cumulativeCommandExecutionInvoluntaryContextSwitches() { |
| return getCumulativeLong(spawnResult -> spawnResult.getNumInvoluntaryContextSwitches()); |
| } |
| |
| /** |
| * Returns the cumulative command execution CPU time for the {@link Action}. |
| * |
| * @return the cumulative measurement, or empty in case of execution errors or when the |
| * measurement is not implemented for the current platform |
| */ |
| public Optional<Duration> cumulativeCommandExecutionCpuTime() { |
| Optional<Duration> userTime = cumulativeCommandExecutionUserTime(); |
| Optional<Duration> systemTime = cumulativeCommandExecutionSystemTime(); |
| |
| if (!userTime.isPresent() && !systemTime.isPresent()) { |
| return Optional.empty(); |
| } else if (userTime.isPresent() && !systemTime.isPresent()) { |
| return userTime; |
| } else if (!userTime.isPresent() && systemTime.isPresent()) { |
| return systemTime; |
| } else { |
| checkState(userTime.isPresent() && systemTime.isPresent()); |
| return Optional.of(userTime.get().plus(systemTime.get())); |
| } |
| } |
| |
| /** Creates an ActionResult given a list of SpawnResults. */ |
| public static ActionResult create(List<SpawnResult> spawnResults) { |
| if (spawnResults == null) { |
| return EMPTY; |
| } else { |
| return builder().setSpawnResults(spawnResults).build(); |
| } |
| } |
| |
| /** Builder for a {@link ActionResult} instance, which is immutable once built. */ |
| @AutoValue.Builder |
| public abstract static class Builder { |
| |
| /** Sets the SpawnResults for the action. */ |
| public abstract Builder setSpawnResults(List<SpawnResult> spawnResults); |
| |
| /** Builds and returns an ActionResult object. */ |
| public abstract ActionResult build(); |
| } |
| } |