Skip to content

Commit

Permalink
Re-implemented progress tracking for file build phase so it updates p…
Browse files Browse the repository at this point in the history
…roperly.
  • Loading branch information
batkinson committed Jan 10, 2017
1 parent d6e8a19 commit bc2dfba
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src/main/java/com/github/batkinson/jrsync/zsync/IOUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public class IOUtil {

public static final int BUFFER_SIZE = 8192;

interface CopyListener {
void copied(int bytes);
}

/**
* Streams the contents of the supplied {@link BlockReadable} object to the
* supplied {@link OutputStream}, stopping once the specified number of
Expand All @@ -22,10 +26,11 @@ public class IOUtil {
* @param in readable to read from
* @param out stream to write to
* @param count number of bytes to copy
* @param listener event handler to tracking copy during long loop, or null
* @throws IOException
* @throws InterruptedException
*/
static void copy(BlockReadable in, OutputStream out, int count) throws IOException, InterruptedException {
static void copy(BlockReadable in, OutputStream out, int count, CopyListener listener) throws IOException, InterruptedException {
byte[] buf = new byte[BUFFER_SIZE];
int remaining = count;
while (remaining > 0) {
Expand All @@ -39,6 +44,10 @@ static void copy(BlockReadable in, OutputStream out, int count) throws IOExcepti
throw new IOException("failed to read content, end of stream");
out.write(buf, 0, read);
remaining -= read;

if (listener != null) {
listener.copied(read);
}
}
}

Expand Down
33 changes: 28 additions & 5 deletions src/main/java/com/github/batkinson/jrsync/zsync/ZSync.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,31 @@ public static void sync(Metadata metadata, File basis, File target, RangeRequest
}
}

/**
* Implements a {@link CopyTracker} that automatically reports sync progress using a {@link ProgressTracker}.
*/
static class CopyTracker implements IOUtil.CopyListener {

ProgressTracker tracker;
long fileSize, copied;
int fileProgress;

CopyTracker(ProgressTracker tracker, long fileSize) {
this.tracker = tracker;
this.fileSize = fileSize;
}

@Override
public void copied(int bytes) {
copied += bytes;
int nextValue = fileSize <= 0 ? 100 : (int) ((((double) copied) / fileSize) * 100);
if (tracker != null && nextValue != fileProgress) {
tracker.onProgress(ProgressTracker.Stage.BUILD, fileProgress);
}
fileProgress = nextValue;
}
}

/**
* Constructs a file from matching local content and multiple ranges of
* remote content. It assumes the server will return ranges in order
Expand All @@ -162,23 +187,21 @@ static void buildFile(Metadata metadata, RandomAccessFile basis, Map<Long, Long>
BlockReadable localInput = new RandomAccessBlockReadable(basis);
int blockSize = metadata.getBlockSize();
long offset = 0, targetSize = metadata.getFileSize();
CopyTracker copyTracker = new CopyTracker(tracker, targetSize);
Range nextRange;
while (offset < targetSize) {

if (Thread.interrupted()) {
throw new InterruptedException();
}

if (tracker != null) {
tracker.onProgress(ProgressTracker.Stage.BUILD, (int) ((double) offset / (targetSize == 0 ? 1 : targetSize) * 100));
}
if (matches.containsKey(offset)) {
basis.seek(matches.get(offset));
copy(localInput, output, blockSize);
copy(localInput, output, blockSize, copyTracker);
offset += blockSize;
} else if ((nextRange = remoteInput.next()) != null && offset == nextRange.first) {
int rangeLength = (int) (nextRange.last - nextRange.first) + 1;
copy(remoteInput, output, rangeLength);
copy(remoteInput, output, rangeLength, copyTracker);
offset += rangeLength;
} else
throw new RuntimeException("no content for offset: " + offset);
Expand Down

0 comments on commit bc2dfba

Please sign in to comment.