/*
 * Copyright (C) 2008-2011, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

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 */); } } }