Skip to content

Commit

Permalink
Implementing a FileSlice tracker to easy the task of detect the seque…
Browse files Browse the repository at this point in the history
…ntial progress of an individual file inside a download.
  • Loading branch information
aldenml committed Jan 26, 2015
1 parent cdf274d commit 894d40f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/com/frostwire/jlibtorrent/FileSlice.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
* starts, and {@link #getSize()} is the number of bytes this range is. The {@code size + offset}
* will never be greater than the file size.
* <p/>
* Note: This class does not store internally a reference to the native swig file_slice. This is because
* we are dealing with only three integral values and we want to avoid keep a reference to a memory in the
* Implementation note: This class does not store internally a reference to the native swig file_slice. This is because
* we are dealing with only three integral values and we want to avoid keeping a reference to a memory in the
* native heap.
*
* @author gubatron
Expand Down
89 changes: 89 additions & 0 deletions src/com/frostwire/jlibtorrent/FileSliceTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.frostwire.jlibtorrent;

import sun.plugin.dom.exception.InvalidStateException;

import java.util.Comparator;
import java.util.PriorityQueue;

/**
* @author gubatron
* @author aldenml
*/
public final class FileSliceTracker {

private final int fileIndex;

private final SortedSlices sortedSlices;

private boolean frozen;
private FileSlice[] slices;
private boolean[] complete;

public FileSliceTracker(int fileIndex) {
this.fileIndex = fileIndex;

this.sortedSlices = new SortedSlices();
this.frozen = false;
}

public int getFileIndex() {
return fileIndex;
}

public void addSlice(FileSlice slice) {

This comment has been minimized.

Copy link
@gubatron

gubatron Jan 26, 2015

Collaborator

Looking at the implementation, let's do this:
public void addSlice(FileSlice slice) throws InvalidStateException, IllegalArgumentException

Principle of Least Astonishment

Don't want to surprise API users with unexpected crashes.

This comment has been minimized.

Copy link
@aldenml

aldenml Jan 26, 2015

Author Collaborator

I will add it because we are in java land, but declaring exceptions in the signature and mandatory try-catch is a thing of the past

This comment has been minimized.

Copy link
@gubatron

gubatron Jan 26, 2015

Collaborator

i guess it also has to do with using or not exceptions for logic flow.

This comment has been minimized.

Copy link
@aldenml

aldenml Jan 26, 2015

Author Collaborator

I'm in the process of removing all this anyway, freeze and checkFrozen is obiuosly a bad design.

if (frozen) {
throw new InvalidStateException("Can't track slice if already frozen");
}

if (slice.getFileIndex() != fileIndex) {
throw new IllegalArgumentException("Invalid file index");
}

sortedSlices.add(slice);
}

public void freeze() {
frozen = true;
slices = sortedSlices.toArray(new FileSlice[0]);
complete = new boolean[slices.length];
}

public int getNumSlices() {
checkFrozen();

return slices.length;
}

public boolean isComplete(int index) {

This comment has been minimized.

Copy link
@gubatron

gubatron Jan 26, 2015

Collaborator

... throws InvalidStateException

checkFrozen();

return complete[index];
}

public void setComplete(int index, boolean complete) {

This comment has been minimized.

Copy link
@gubatron

gubatron Jan 26, 2015

Collaborator

... throws InvalidStateException

checkFrozen();

this.complete[index] = complete;
}

private void checkFrozen() {
if (!frozen) {
throw new InvalidStateException("Tracker needs to be frozen");
}
}

private static final class SortedSlices extends PriorityQueue<FileSlice> {

public SortedSlices() {
super(new FileSliceComparator());
}
}

private static final class FileSliceComparator implements Comparator<FileSlice> {

@Override
public int compare(FileSlice o1, FileSlice o2) {
return Long.compare(o1.getOffset(), o2.getOffset());
}
}
}
11 changes: 6 additions & 5 deletions src/com/frostwire/jlibtorrent/TorrentInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,20 +227,21 @@ public List<WebSeedEntry> getWebSeeds() {
* @return
*/
public long getTotalSize() {
return this.ti.total_size();
return ti.total_size();
}

/**
* The number of byte for each piece.
* <p/>
* The difference between piece_size() and piece_length() is that piece_size() takes
* the piece index as argument and gives you the exact size of that piece. It will always
* be the same as piece_length() except in the case of the last piece, which may be smaller.
* The difference between {@link #getPieceSize(int)} and {@link #getPieceLength()} is that
* {@link #getPieceSize(int)} takes the piece index as argument and gives you the exact size
* of that piece. It will always be the same as {@link #getPieceLength()} except in the case
* of the last piece, which may be smaller.
*
* @return
*/
public int getPieceLength() {
return this.ti.piece_length();
return ti.piece_length();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/**
* This alert is posted when a torrent completes checking. i.e. when it transitions
* out of the ``checking files`` state into a state where it is ready to start downloading
* out of the ``checking files`` state into a state where it is ready to start downloading.
*
* @author gubatron
* @author aldenml
Expand Down
4 changes: 2 additions & 2 deletions src/com/frostwire/jlibtorrent/alerts/TorrentUpdateAlert.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
* specific cases. For instance, when a torrent is downloaded from a URL, the true info
* hash is not known immediately. First the .torrent file must be downloaded and parsed.
* <p/>
* Once this download completes, the ``torrent_update_alert`` is posted to notify the client
* of the info-hash changing.
* Once this download completes, the {@link com.frostwire.jlibtorrent.alerts.TorrentUpdateAlert} is
* posted to notify the client of the info-hash changing.
*
* @author gubatron
* @author aldenml
Expand Down
56 changes: 56 additions & 0 deletions src/com/frostwire/jlibtorrent/demo/PieceMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.frostwire.jlibtorrent.demo;

import com.frostwire.jlibtorrent.FileSlice;
import com.frostwire.jlibtorrent.FileSliceTracker;
import com.frostwire.jlibtorrent.TorrentInfo;

import java.io.File;
import java.util.ArrayList;

/**
* @author gubatron
* @author aldenml
*/
public final class PieceMap {


public static void main(String[] args) throws Throwable {

// comment this line for a real application
args = new String[]{"/Users/aldenml/Downloads/ReSet_Resynthformation_SOSEP051_FrostClick_FrostWire_6_28_2014.torrent"};

File torrentFile = new File(args[0]);

TorrentInfo ti = new TorrentInfo(torrentFile);

int numPieces = ti.getNumPieces();

System.out.println("Num Pieces: " + numPieces);

FileSliceTracker[] trackers = new FileSliceTracker[ti.getNumFiles()];

for (int i = 0; i < numPieces; i++) {
ArrayList<FileSlice> slices = ti.mapBlock(i, 0, ti.getPieceSize(i));

This comment has been minimized.

Copy link
@gubatron

gubatron Jan 26, 2015

Collaborator

very cool

for (FileSlice slice : slices) {
int fileIndex = slice.getFileIndex();

if (trackers[fileIndex] == null) {
trackers[fileIndex] = new FileSliceTracker(fileIndex);
}

trackers[fileIndex].addSlice(slice);
}
}

int totalSlices = 0;

for (FileSliceTracker tracker : trackers) {
tracker.freeze();
int numSlices = tracker.getNumSlices();
System.out.println("File Index: " + tracker.getFileIndex() + ", slices: " + numSlices);
totalSlices = totalSlices + numSlices;
}

System.out.println("Total Slices: " + totalSlices);
}
}

0 comments on commit 894d40f

Please sign in to comment.