/*
 * Copyright (C) 2008-2011, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.lib;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.lib.internal.WorkQueue;

ProgressMonitor that batches update events.
/** * ProgressMonitor that batches update events. */
public abstract class BatchingProgressMonitor implements ProgressMonitor { private long delayStartTime; private TimeUnit delayStartUnit = TimeUnit.MILLISECONDS; private Task task;
Set an optional delay before the first output.
Params:
  • time – how long to wait before output. If 0 output begins on the first update(int) call.
  • unit – time unit of time.
/** * Set an optional delay before the first output. * * @param time * how long to wait before output. If 0 output begins on the * first {@link #update(int)} call. * @param unit * time unit of {@code time}. */
public void setDelayStart(long time, TimeUnit unit) { delayStartTime = time; delayStartUnit = unit; }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void start(int totalTasks) { // Ignore the number of tasks. }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void beginTask(String title, int work) { endTask(); task = new Task(title, work); if (delayStartTime != 0) task.delay(delayStartTime, delayStartUnit); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void update(int completed) { if (task != null) task.update(this, completed); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void endTask() { if (task != null) { task.end(this); task = null; } }
{@inheritDoc}
/** {@inheritDoc} */
@Override public boolean isCancelled() { return false; }
Update the progress monitor if the total work isn't known,
Params:
  • taskName – name of the task.
  • workCurr – number of units already completed.
/** * Update the progress monitor if the total work isn't known, * * @param taskName * name of the task. * @param workCurr * number of units already completed. */
protected abstract void onUpdate(String taskName, int workCurr);
Finish the progress monitor when the total wasn't known in advance.
Params:
  • taskName – name of the task.
  • workCurr – total number of units processed.
/** * Finish the progress monitor when the total wasn't known in advance. * * @param taskName * name of the task. * @param workCurr * total number of units processed. */
protected abstract void onEndTask(String taskName, int workCurr);
Update the progress monitor when the total is known in advance.
Params:
  • taskName – name of the task.
  • workCurr – number of units already completed.
  • workTotal – estimated number of units to process.
  • percentDone – workCurr * 100 / workTotal.
/** * Update the progress monitor when the total is known in advance. * * @param taskName * name of the task. * @param workCurr * number of units already completed. * @param workTotal * estimated number of units to process. * @param percentDone * {@code workCurr * 100 / workTotal}. */
protected abstract void onUpdate(String taskName, int workCurr, int workTotal, int percentDone);
Finish the progress monitor when the total is known in advance.
Params:
  • taskName – name of the task.
  • workCurr – total number of units processed.
  • workTotal – estimated number of units to process.
  • percentDone – workCurr * 100 / workTotal.
/** * Finish the progress monitor when the total is known in advance. * * @param taskName * name of the task. * @param workCurr * total number of units processed. * @param workTotal * estimated number of units to process. * @param percentDone * {@code workCurr * 100 / workTotal}. */
protected abstract void onEndTask(String taskName, int workCurr, int workTotal, int percentDone); private static class Task implements Runnable {
Title of the current task.
/** Title of the current task. */
private final String taskName;
Number of work units, or ProgressMonitor.UNKNOWN.
/** Number of work units, or {@link ProgressMonitor#UNKNOWN}. */
private final int totalWork;
True when timer expires and output should occur on next update.
/** True when timer expires and output should occur on next update. */
private volatile boolean display;
Scheduled timer, supporting cancellation if task ends early.
/** Scheduled timer, supporting cancellation if task ends early. */
private Future<?> timerFuture;
True if the task has displayed anything.
/** True if the task has displayed anything. */
private boolean output;
Number of work units already completed.
/** Number of work units already completed. */
private int lastWork;
Percentage of totalWork that is done.
/** Percentage of {@link #totalWork} that is done. */
private int lastPercent; Task(String taskName, int totalWork) { this.taskName = taskName; this.totalWork = totalWork; this.display = true; } void delay(long time, TimeUnit unit) { display = false; timerFuture = WorkQueue.getExecutor().schedule(this, time, unit); } @Override public void run() { display = true; } void update(BatchingProgressMonitor pm, int completed) { lastWork += completed; if (totalWork == UNKNOWN) { // Only display once per second, as the alarm fires. if (display) { pm.onUpdate(taskName, lastWork); output = true; restartTimer(); } } else { // Display once per second or when 1% is done. int currPercent = lastWork * 100 / totalWork; if (display) { pm.onUpdate(taskName, lastWork, totalWork, currPercent); output = true; restartTimer(); lastPercent = currPercent; } else if (currPercent != lastPercent) { pm.onUpdate(taskName, lastWork, totalWork, currPercent); output = true; lastPercent = currPercent; } } } private void restartTimer() { display = false; timerFuture = WorkQueue.getExecutor().schedule(this, 1, TimeUnit.SECONDS); } void end(BatchingProgressMonitor pm) { if (output) { if (totalWork == UNKNOWN) { pm.onEndTask(taskName, lastWork); } else { int pDone = lastWork * 100 / totalWork; pm.onEndTask(taskName, lastWork, totalWork, pDone); } } if (timerFuture != null) timerFuture.cancel(false /* no interrupt */); } } }