aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/runtime')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java88
1 files changed, 80 insertions, 8 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
index e4b0128e3a..b852de611a 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
@@ -43,13 +43,18 @@ import java.util.logging.Logger;
public class ExperimentalEventHandler extends BlazeCommandEventHandler {
private static Logger LOG = Logger.getLogger(ExperimentalEventHandler.class.getName());
+ private final long minimalDelayMillis;
private final boolean cursorControl;
+ private final Clock clock;
private final AnsiTerminal terminal;
private final boolean debugAllEvents;
private final ExperimentalStateTracker stateTracker;
+ private final long minimalUpdateInterval;
+ private long lastRefreshMillis;
private int numLinesProgressBar;
private boolean buildComplete;
private boolean progressBarNeedsRefresh;
+ private Thread updateThread;
public final int terminalWidth;
@@ -59,9 +64,14 @@ public class ExperimentalEventHandler extends BlazeCommandEventHandler {
this.cursorControl = options.useCursorControl();
this.terminal = new AnsiTerminal(outErr.getErrorStream());
this.terminalWidth = (options.terminalColumns > 0 ? options.terminalColumns : 80);
+ this.clock = clock;
this.debugAllEvents = options.experimentalUiDebugAllEvents;
this.stateTracker = new ExperimentalStateTracker(clock);
this.numLinesProgressBar = 0;
+ this.minimalDelayMillis = Math.round(options.showProgressRateLimit * 1000);
+ this.minimalUpdateInterval = Math.max(this.minimalDelayMillis, 1000L);
+ // The progress bar has not been updated yet.
+ ignoreRefreshLimitOnce();
}
@Override
@@ -150,13 +160,18 @@ public class ExperimentalEventHandler extends BlazeCommandEventHandler {
@Subscribe
public void buildStarted(BuildStartingEvent event) {
stateTracker.buildStarted(event);
+ // As a new phase started, inform immediately.
+ ignoreRefreshLimitOnce();
refresh();
}
@Subscribe
public void loadingStarted(LoadingPhaseStartedEvent event) {
stateTracker.loadingStarted(event);
+ // As a new phase started, inform immediately.
+ ignoreRefreshLimitOnce();
refresh();
+ startUpdateThread();
}
@Subscribe
@@ -174,6 +189,9 @@ public class ExperimentalEventHandler extends BlazeCommandEventHandler {
@Subscribe
public void progressReceiverAvailable(ExecutionProgressReceiverAvailableEvent event) {
stateTracker.progressReceiverAvailable(event);
+ // As this is the first time we have a progress message, update immediately.
+ ignoreRefreshLimitOnce();
+ startUpdateThread();
}
@Subscribe
@@ -181,11 +199,13 @@ public class ExperimentalEventHandler extends BlazeCommandEventHandler {
stateTracker.buildComplete(event);
refresh();
buildComplete = true;
+ stopUpdateThread();
}
@Subscribe
public void noBuild(NoBuildEvent event) {
buildComplete = true;
+ stopUpdateThread();
}
@Subscribe
@@ -206,15 +226,67 @@ public class ExperimentalEventHandler extends BlazeCommandEventHandler {
}
private synchronized void doRefresh() {
- try {
- if (progressBarNeedsRefresh) {
- progressBarNeedsRefresh = false;
- clearProgressBar();
- addProgressBar();
- terminal.flush();
+ long nowMillis = clock.currentTimeMillis();
+ if (lastRefreshMillis + minimalDelayMillis < nowMillis) {
+ try {
+ if (progressBarNeedsRefresh || stateTracker.progressBarTimeDependent()) {
+ progressBarNeedsRefresh = false;
+ lastRefreshMillis = nowMillis;
+ clearProgressBar();
+ addProgressBar();
+ terminal.flush();
+ }
+ } catch (IOException e) {
+ LOG.warning("IO Error writing to output stream: " + e);
}
- } catch (IOException e) {
- LOG.warning("IO Error writing to output stream: " + e);
+ if (!stateTracker.progressBarTimeDependent()) {
+ stopUpdateThread();
+ }
+ } else {
+ // We skipped an update due to rate limiting. If this however, turned
+ // out to be the last update for a long while, we need to show it in a
+ // timely manner, as it best describes the current state.
+ startUpdateThread();
+ }
+ }
+
+ private void ignoreRefreshLimitOnce() {
+ // Set refresh time variables in a state such that the next progress bar
+ // update will definitely be written out.
+ lastRefreshMillis = clock.currentTimeMillis() - minimalDelayMillis - 1;
+ }
+
+ private synchronized void startUpdateThread() {
+ if (updateThread == null) {
+ final ExperimentalEventHandler eventHandler = this;
+ updateThread =
+ new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ Thread.sleep(minimalUpdateInterval);
+ eventHandler.doRefresh();
+ }
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ });
+ updateThread.start();
+ }
+ }
+
+ private synchronized void stopUpdateThread() {
+ if (updateThread != null) {
+ updateThread.interrupt();
+ try {
+ updateThread.join();
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ updateThread = null;
}
}