blob: 5f20e945ed6de72f62321568247e91c18db1814c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ignite.internal.commandline;
import java.io.PrintStream;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.internal.util.GridStringBuilder;
/**
* Class for printing progress of some task.
* Progress is printed {@code chunksNum} times.
*/
public class ProgressPrinter {
/** */
private static final int DEFAULT_CHUNKS_NUM = 50;
/** */
private static final int MIN_PROGRESS_BAR_LENGTH = 20;
/** */
private static final int MAX_CAPTION_LENGTH = 40;
/** */
private final long total;
/** */
private long curr = 0;
/** */
private final int chunksNum;
/** */
private final String caption;
/** */
private final PrintStream printStream;
/** */
private int lastChunkLogged = -1;
/** */
private Long timeStarted = null;
/**
* Constructor.
*
* @param caption Caption.
* @param total Total count of items to process.
*/
public ProgressPrinter(PrintStream printStream, String caption, long total) {
this(printStream, caption, total, DEFAULT_CHUNKS_NUM);
}
/**
* Constructor.
*
* @param caption Caption.
* @param total Total count of items to process.
* @param chunksNum Number of progress bar chunks to print.
*/
public ProgressPrinter(PrintStream printStream, String caption, long total, int chunksNum) {
this.printStream = printStream;
this.caption = caption.length() >= MAX_CAPTION_LENGTH ? caption.substring(0, MAX_CAPTION_LENGTH) : caption;
this.total = total;
this.chunksNum = chunksNum;
}
/**
* Prints current progress.
*/
public void printProgress() {
curr++;
if (curr > total)
throw new RuntimeException("Current value can't be greater than total value.");
if (timeStarted == null)
timeStarted = System.currentTimeMillis();
final double currRatio = (double)curr / total;
final int currChunk = (int)(currRatio * chunksNum);
if (currChunk > lastChunkLogged || curr == total) {
lastChunkLogged++;
printProgress0(curr, currRatio);
}
}
/** */
private void printProgress0(long curr, double currRatio) {
int progressBarLen = MIN_PROGRESS_BAR_LENGTH + (MAX_CAPTION_LENGTH - caption.length());
String progressBarFmt = "\r%s %4s [%" + progressBarLen + "s] %-50s";
int percentage = (int)(currRatio * 100);
int progressCurrLen = (int)(currRatio * progressBarLen);
long timeRunning = System.currentTimeMillis() - timeStarted;
long timeEstimated = (long)(timeRunning / currRatio);
GridStringBuilder progressBuilder = new GridStringBuilder();
for (int i = 0; i < progressBarLen; i++)
progressBuilder.a(i < progressCurrLen ? "=" : " ");
long daysRunning = TimeUnit.MILLISECONDS.toDays(timeRunning);
long daysEstimated = TimeUnit.MILLISECONDS.toDays(timeEstimated);
String txtProgress = String.format(
"%s/%s (%s%s / %s%s)",
curr,
total,
daysRunning > 0 ? daysRunning + " days " : "",
formatDuration(timeRunning),
daysEstimated > 0 ? daysEstimated + " days " : "",
formatDuration(timeEstimated)
);
String progressBar = String.format(
progressBarFmt,
caption + ":",
percentage + "%",
progressBuilder.toString(),
txtProgress
);
printStream.print(progressBar);
}
/**
* Formats the given duration in milliseconds in "HH:mm:ss" format.
*/
private static String formatDuration(long durationMillis) {
long seconds = (durationMillis / 1000) % 60;
long minutes = (durationMillis / (1000 * 60)) % 60;
long hours = durationMillis / (1000 * 60 * 60);
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
}