aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java89
1 files changed, 67 insertions, 22 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
index 5df6a8dcdb..1995ebd325 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
@@ -48,6 +48,7 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.stream.Stream;
/**
* An experimental state tracker for the new experimental UI.
@@ -58,7 +59,8 @@ class ExperimentalStateTracker {
static final String ELLIPSIS = "...";
static final String FETCH_PREFIX = " Fetching ";
static final String AND_MORE = " ...";
-
+ static final String NO_STATUS = "-----";
+ static final int STATUS_LENGTH = 5;
static final int NANOS_PER_SECOND = 1000000000;
static final String URL_PROTOCOL_SEP = "://";
@@ -79,7 +81,8 @@ class ExperimentalStateTracker {
private final Deque<String> runningActions;
private final Map<String, Action> actions;
private final Map<String, Long> actionNanoStartTimes;
- private final Map<String, String> actionStrategy;
+ private final Map<String, String> actionStatus;
+ private final Set<String> executingActions;
// running downloads are identified by the original URL they were trying to
// access.
@@ -112,8 +115,9 @@ class ExperimentalStateTracker {
ExperimentalStateTracker(Clock clock, int targetWidth) {
this.runningActions = new ArrayDeque<>();
this.actions = new TreeMap<>();
+ this.executingActions = new TreeSet<>();
this.actionNanoStartTimes = new TreeMap<>();
- this.actionStrategy = new TreeMap<>();
+ this.actionStatus = new TreeMap<>();
this.testActions = new TreeMap<>();
this.runningDownloads = new ArrayDeque<>();
this.downloads = new TreeMap<>();
@@ -248,12 +252,14 @@ class ExperimentalStateTracker {
String name = event.getActionMetadata().getPrimaryOutput().getPath().getPathString();
if (strategy != null) {
synchronized (this) {
- actionStrategy.put(name, strategy);
+ actionStatus.put(name, strategy);
+ executingActions.add(name);
}
} else {
String message = event.getMessage();
synchronized (this) {
- actionStrategy.put(name, message);
+ actionStatus.put(name, message);
+ executingActions.remove(name);
}
}
}
@@ -263,9 +269,10 @@ class ExperimentalStateTracker {
Action action = event.getAction();
String name = action.getPrimaryOutput().getPath().getPathString();
runningActions.remove(name);
+ executingActions.remove(name);
actions.remove(name);
actionNanoStartTimes.remove(name);
- actionStrategy.remove(name);
+ actionStatus.remove(name);
if (action.getOwner() != null) {
Label owner = action.getOwner().getLabel();
@@ -393,9 +400,22 @@ class ExperimentalStateTracker {
}
String postfix = "";
+ String prefix = "";
long nanoRuntime = nanoTime - actionNanoStartTimes.get(name);
long runtimeSeconds = nanoRuntime / NANOS_PER_SECOND;
- String strategy = actionStrategy.get(name);
+ String strategy = null;
+ if (executingActions.contains(name)) {
+ strategy = actionStatus.get(name);
+ } else {
+ String status = actionStatus.get(name);
+ if (status == null) {
+ status = NO_STATUS;
+ }
+ if (status.length() > STATUS_LENGTH) {
+ status = status.substring(0, STATUS_LENGTH);
+ }
+ prefix = prefix + "[" + status + "] ";
+ }
// To keep the UI appearance more stable, always show the elapsed
// time if we also show a strategy (otherwise the strategy will jump in
// the progress bar).
@@ -412,10 +432,10 @@ class ExperimentalStateTracker {
}
if (desiredWidth <= 0) {
- return message + postfix;
+ return prefix + message + postfix;
}
- if (message.length() + postfix.length() <= desiredWidth) {
- return message + postfix;
+ if (prefix.length() + message.length() + postfix.length() <= desiredWidth) {
+ return prefix + message + postfix;
}
// We have to shorten the message to fit into the line.
@@ -428,31 +448,56 @@ class ExperimentalStateTracker {
if (pathIndex >= 0) {
String start = message.substring(0, pathIndex);
String end = message.substring(pathIndex + pathString.length());
- int pathTargetLength = desiredWidth - start.length() - end.length() - postfix.length();
+ int pathTargetLength =
+ desiredWidth - start.length() - end.length() - postfix.length() - prefix.length();
// This attempt of shortening is reasonable if what is left from the label
// is significantly longer (twice as long) as the ellipsis symbols introduced.
if (pathTargetLength >= 3 * ELLIPSIS.length()) {
String shortPath = suffix(pathString, pathTargetLength - ELLIPSIS.length());
int slashPos = shortPath.indexOf('/');
if (slashPos >= 0) {
- return start + ELLIPSIS + shortPath.substring(slashPos) + end + postfix;
+ return prefix + start + ELLIPSIS + shortPath.substring(slashPos) + end + postfix;
}
}
}
// Second attempt: just take a shortened version of the label.
String shortLabel =
- shortenedLabelString(action.getOwner().getLabel(), desiredWidth - postfix.length());
- if (shortLabel.length() + postfix.length() <= desiredWidth) {
- return shortLabel + postfix;
+ shortenedLabelString(
+ action.getOwner().getLabel(), desiredWidth - postfix.length() - prefix.length());
+ if (prefix.length() + shortLabel.length() + postfix.length() <= desiredWidth) {
+ return prefix + shortLabel + postfix;
}
}
}
- if (3 * ELLIPSIS.length() + postfix.length() <= desiredWidth) {
- message = ELLIPSIS + suffix(message, desiredWidth - ELLIPSIS.length() - postfix.length());
+ if (3 * ELLIPSIS.length() + postfix.length() + prefix.length() <= desiredWidth) {
+ message =
+ ELLIPSIS
+ + suffix(
+ message, desiredWidth - ELLIPSIS.length() - postfix.length() - prefix.length());
}
- return message + postfix;
+ return prefix + message + postfix;
+ }
+
+ /**
+ * Stream of actions in decreasing order of importance for the UI. I.e., first have all executing
+ * actions and then all non-executing actions, each time in order of increasing start time.
+ */
+ private Stream<String> sortedActions() {
+ return Stream.concat(
+ runningActions.stream().filter(s -> executingActions.contains(s)),
+ runningActions.stream().filter(s -> !executingActions.contains(s)));
+ }
+
+ private String countActions() {
+ if (runningActions.size() == 1) {
+ return " 1 action";
+ } else if (runningActions.size() == executingActions.size()) {
+ return "" + runningActions.size() + " actions running";
+ } else {
+ return "" + runningActions.size() + " actions, " + executingActions.size() + " running";
+ }
}
private void sampleOldestActions(AnsiTerminalWriter terminalWriter) throws IOException {
@@ -461,7 +506,7 @@ class ExperimentalStateTracker {
long nanoTime = clock.nanoTime();
int actionCount = runningActions.size();
Set<String> toSkip = new TreeSet<>();
- for (String action : runningActions) {
+ for (String action : (Iterable<String>) sortedActions()::iterator) {
totalCount++;
if (toSkip.contains(action)) {
continue;
@@ -767,14 +812,14 @@ class ExperimentalStateTracker {
if (shortVersion) {
String statusMessage =
describeAction(
- runningActions.peekFirst(),
+ sortedActions().findFirst().get(),
clock.nanoTime(),
targetWidth - terminalWriter.getPosition(),
null);
- statusMessage += " ... (" + runningActions.size() + " actions)";
+ statusMessage += " ... (" + countActions() + ")";
terminalWriter.normal().append(" " + statusMessage);
} else {
- String statusMessage = "" + runningActions.size() + " actions";
+ String statusMessage = countActions();
terminalWriter.normal().append(" " + statusMessage);
maybeShowRecentTest(
terminalWriter, shortVersion, targetWidth - terminalWriter.getPosition());