package com.frostwire.jlibtorrent;
import com.frostwire.jlibtorrent.swig.*;
import com.frostwire.jlibtorrent.swig.torrent_handle.status_flags_t;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* You will usually have to store your torrent handles somewhere, since it's
* the object through which you retrieve information about the torrent and
* aborts the torrent.
* <p/>
* .. warning::
* Any member function that returns a value or fills in a value has to be
* made synchronously. This means it has to wait for the main thread to
* complete the query before it can return. This might potentially be
* expensive if done from within a GUI thread that needs to stay
* responsive. Try to avoid quering for information you don't need, and
* try to do it in as few calls as possible. You can get most of the
* interesting information about a torrent from the
* torrent_handle::status() call.
* <p/>
* The default constructor will initialize the handle to an invalid state.
* Which means you cannot perform any operation on it, unless you first
* assign it a valid handle. If you try to perform any operation on an
* uninitialized handle, it will throw ``invalid_handle``.
* <p/>
* .. warning::
* All operations on a torrent_handle may throw libtorrent_exception
* exception, in case the handle is no longer refering to a torrent.
* There is one exception is_valid() will never throw. Since the torrents
* are processed by a background thread, there is no guarantee that a
* handle will remain valid between two calls.
*
* @author gubatron
* @author aldenml
*/
public final class TorrentHandle {
private static final long REQUEST_STATUS_RESOLUTION_MILLIS = 500;
private final torrent_handle th;
private long lastStatusRequestTime;
private TorrentStatus lastStatus;
public TorrentHandle(torrent_handle th) {
this.th = th;
}
public torrent_handle getSwig() {
return th;
}
/**
* This function starts an asynchronous read operation of the specified
* piece from this torrent. You must have completed the download of the
* specified piece before calling this function.
* <p/>
* When the read operation is completed, it is passed back through an
* alert, read_piece_alert. Since this alert is a reponse to an explicit
* call, it will always be posted, regardless of the alert mask.
* <p/>
* Note that if you read multiple pieces, the read operations are not
* guaranteed to finish in the same order as you initiated them.
*
* @param piece
*/
public void readPiece(int piece) {
th.read_piece(piece);
}
/**
* Returns true if this piece has been completely downloaded, and false
* otherwise.
*
* @param piece
* @return
*/
public boolean havePiece(int piece) {
return th.have_piece(piece);
}
/**
* takes a reference to a vector that will be cleared and filled with one
* entry for each peer connected to this torrent, given the handle is
* valid. If the torrent_handle is invalid, it will return an empty list.
* <p/>
* Each entry in the vector contains
* information about that particular peer. See peer_info.
*
* @return
*/
public List<PeerInfo> getPeerInfo() {
if (!th.is_valid()) {
return Collections.emptyList();
}
peer_info_vector v = new peer_info_vector();
th.get_peer_info(v);
int size = (int) v.size();
List<PeerInfo> l = new ArrayList<PeerInfo>(size);
for (int i = 0; i < size; i++) {
l.add(new PeerInfo(v.get(i)));
}
return l;
}
/**
* Returns a pointer to the torrent_info object associated with this
* torrent. The torrent_info object may be a copy of the internal object.
* If the torrent doesn't have metadata, the pointer will not be
* initialized (i.e. a NULL pointer). The torrent may be in a state
* without metadata only if it was started without a .torrent file, e.g.
* by using the libtorrent extension of just supplying a tracker and
* info-hash.
*
* @return
*/
public TorrentInfo getTorrentInfo() {
torrent_info ti = th.torrent_file();
return ti != null ? new TorrentInfo(th.torrent_file()) : null;
}
/**
* `status()`` will return a structure with information about the status
* of this torrent. If the torrent_handle is invalid, it will throw
* libtorrent_exception exception. See torrent_status. The ``flags``
* argument filters what information is returned in the torrent_status.
* Some information in there is relatively expensive to calculate, and if
* you're not interested in it (and see performance issues), you can
* filter them out.
* <p/>
* By default everything is included. The flags you can use to decide
* what to *include* are defined in the status_flags_t enum.
* <p/>
* It is important not to call this method for each field in the status
* for performance reasons.
*
* @return
*/
public TorrentStatus getStatus(boolean force) {
long now = System.currentTimeMillis();
if (force || (now - lastStatusRequestTime) >= REQUEST_STATUS_RESOLUTION_MILLIS) {
lastStatusRequestTime = now;
lastStatus = new TorrentStatus(th.status());
}
return lastStatus;
}
/**
* `status()`` will return a structure with information about the status
* of this torrent. If the torrent_handle is invalid, it will throw
* libtorrent_exception exception. See torrent_status. The ``flags``
* argument filters what information is returned in the torrent_status.
* Some information in there is relatively expensive to calculate, and if
* you're not interested in it (and see performance issues), you can
* filter them out.
*
* @return
*/
public TorrentStatus getStatus() {
return this.getStatus(false);
}
/**
* returns the info-hash for the torrent.
*
* @return
*/
public Sha1Hash getInfoHash() {
return new Sha1Hash(th.info_hash());
}
/**
* ``pause()`` will disconnect all peers.
* <p/>
* When a torrent is paused, it will however
* remember all share ratios to all peers and remember all potential (not
* connected) peers. Torrents may be paused automatically if there is a
* file error (e.g. disk full) or something similar. See
* file_error_alert.
* <p/>
* To know if a torrent is paused or not, call
* ``torrent_handle::status()`` and inspect ``torrent_status::paused``.
* <p/>
* The ``flags`` argument to pause can be set to
* ``torrent_handle::graceful_pause`` which will delay the disconnect of
* peers that we're still downloading outstanding requests from. The
* torrent will not accept any more requests and will disconnect all idle
* peers. As soon as a peer is done transferring the blocks that were
* requested from it, it is disconnected. This is a graceful shut down of
* the torrent in the sense that no downloaded bytes are wasted.
* <p/>
* torrents that are auto-managed may be automatically resumed again. It
* does not make sense to pause an auto-managed torrent without making it
* not automanaged first.
* <p/>
* The current {@link Session} add torrent implementations add the torrent
* in no-auto-managed mode.
*/
public void pause() {
th.pause();
}
/**
* ``resume()`` will reconnect all peers.
* <p/>
* Torrents that are auto-managed may be automatically resumed again.
*/
public void resume() {
th.resume();
}
/**
* This function returns true if any whole chunk has been downloaded
* since the torrent was first loaded or since the last time the resume
* data was saved. When saving resume data periodically, it makes sense
* to skip any torrent which hasn't downloaded anything since the last
* time.
* <p/>
* .. note::
* A torrent's resume data is considered saved as soon as the alert is
* posted. It is important to make sure this alert is received and
* handled in order for this function to be meaningful.
*
* @return
*/
public boolean needSaveResumeData() {
return th.need_save_resume_data();
}
/**
* changes whether the torrent is auto managed or not. For more info,
* see queuing_.
*
* @param value
*/
public void setAutoManaged(boolean value) {
th.auto_managed(value);
}
/**
* Every torrent that is added is assigned a queue position exactly one
* greater than the greatest queue position of all existing torrents.
* Torrents that are being seeded have -1 as their queue position, since
* they're no longer in line to be downloaded.
* <p/>
* When a torrent is removed or turns into a seed, all torrents with
* greater queue positions have their positions decreased to fill in the
* space in the sequence.
* <p/>
* This function returns the torrent's position in the download
* queue. The torrents with the smallest numbers are the ones that are
* being downloaded. The smaller number, the closer the torrent is to the
* front of the line to be started.
* <p/>
* The queue position is also available in the torrent_status.
*
* @return
*/
public int getQueuePosition() {
return th.queue_position();
}
/**
* The ``queue_position_*()`` functions adjust the torrents position in
* the queue. Up means closer to the front and down means closer to the
* back of the queue. Top and bottom refers to the front and the back of
* the queue respectively.
*/
public void queuePositionUp() {
th.queue_position_up();
}
/**
* The ``queue_position_*()`` functions adjust the torrents position in
* the queue. Up means closer to the front and down means closer to the
* back of the queue. Top and bottom refers to the front and the back of
* the queue respectively.
*/
public void queuePositionDown() {
th.queue_position_down();
}
/**
* The ``queue_position_*()`` functions adjust the torrents position in
* the queue. Up means closer to the front and down means closer to the
* back of the queue. Top and bottom refers to the front and the back of
* the queue respectively.
*/
public void queuePositionTop() {
th.queue_position_top();
}
/**
* The ``queue_position_*()`` functions adjust the torrents position in
* the queue. Up means closer to the front and down means closer to the
* back of the queue. Top and bottom refers to the front and the back of
* the queue respectively.
*/
public void queuePositionBottom() {
th.queue_position_bottom();
}
/**
* ``save_resume_data()`` generates fast-resume data and returns it as an
* entry. This entry is suitable for being bencoded. For more information
* about how fast-resume works, see fast-resume_.
* <p/>
* The ``flags`` argument is a bitmask of flags ORed together. see
* save_resume_flags_t
* <p/>
* This operation is asynchronous, ``save_resume_data`` will return
* immediately. The resume data is delivered when it's done through an
* save_resume_data_alert.
* <p/>
* The fast resume data will be empty in the following cases:
* <p/>
* 1. The torrent handle is invalid.
* 2. The torrent is checking (or is queued for checking) its storage, it
* will obviously not be ready to write resume data.
* 3. The torrent hasn't received valid metadata and was started without
* metadata (see libtorrent's metadata-from-peers_ extension)
* <p/>
* Note that by the time you receive the fast resume data, it may already
* be invalid if the torrent is still downloading! The recommended
* practice is to first pause the session, then generate the fast resume
* data, and then close it down. Make sure to not remove_torrent() before
* you receive the save_resume_data_alert though. There's no need to
* pause when saving intermittent resume data.
* <p/>
* .. warning::
* If you pause every torrent individually instead of pausing the
* session, every torrent will have its paused state saved in the
* resume data!
* <p/>
* .. warning::
* The resume data contains the modification timestamps for all files.
* If one file has been modified when the torrent is added again, the
* will be rechecked. When shutting down, make sure to flush the disk
* cache before saving the resume data. This will make sure that the
* file timestamps are up to date and won't be modified after saving
* the resume data. The recommended way to do this is to pause the
* torrent, which will flush the cache and disconnect all peers.
* <p/>
* .. note::
* It is typically a good idea to save resume data whenever a torrent
* is completed or paused. In those cases you don't need to pause the
* torrent or the session, since the torrent will do no more writing to
* its files. If you save resume data for torrents when they are
* paused, you can accelerate the shutdown process by not saving resume
* data again for paused torrents. Completed torrents should have their
* resume data saved when they complete and on exit, since their
* statistics might be updated.
* <p/>
* In full allocation mode the reume data is never invalidated by
* subsequent writes to the files, since pieces won't move around. This
* means that you don't need to pause before writing resume data in full
* or sparse mode. If you don't, however, any data written to disk after
* you saved resume data and before the session closed is lost.
* <p/>
* It also means that if the resume data is out dated, libtorrent will
* not re-check the files, but assume that it is fairly recent. The
* assumption is that it's better to loose a little bit than to re-check
* the entire file.
* <p/>
* It is still a good idea to save resume data periodically during
* download as well as when closing down.
* <p/>
* Example code to pause and save resume data for all torrents and wait
* for the alerts:
* <p/>
* .. code:: c++
* <p/>
* extern int outstanding_resume_data; // global counter of outstanding resume data
* std::vector<torrent_handle> handles = ses.get_torrents();
* ses.pause();
* for (std::vector<torrent_handle>::iterator i = handles.begin();
* i != handles.end(); ++i)
* {
* torrent_handle& h = *i;
* if (!h.is_valid()) continue;
* torrent_status s = h.status();
* if (!s.has_metadata) continue;
* if (!s.need_save_resume_data()) continue;
* <p/>
* h.save_resume_data();
* ++outstanding_resume_data;
* }
* <p/>
* while (outstanding_resume_data > 0)
* {
* alert const* a = ses.wait_for_alert(seconds(10));
* <p/>
* // if we don't get an alert within 10 seconds, abort
* if (a == 0) break;
* <p/>
* std::auto_ptr<alert> holder = ses.pop_alert();
* <p/>
* if (alert_cast<save_resume_data_failed_alert>(a))
* {
* process_alert(a);
* --outstanding_resume_data;
* continue;
* }
* <p/>
* save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(a);
* if (rd == 0)
* {
* process_alert(a);
* continue;
* }
* <p/>
* torrent_handle h = rd->handle;
* torrent_status st = h.status(torrent_handle::query_save_path | torrent_handle::query_name);
* std::ofstream out((st.save_path
* + "/" + st.name + ".fastresume").c_str()
* , std::ios_base::binary);
* out.unsetf(std::ios_base::skipws);
* bencode(std::ostream_iterator<char>(out), *rd->resume_data);
* --outstanding_resume_data;
* }
* <p/>
* .. note::
* Note how ``outstanding_resume_data`` is a global counter in this
* example. This is deliberate, otherwise there is a race condition for
* torrents that was just asked to save their resume data, they posted
* the alert, but it has not been received yet. Those torrents would
* report that they don't need to save resume data again, and skipped by
* the initial loop, and thwart the counter otherwise.
*/
public void saveResumeData() {
th.save_resume_data(torrent_handle.save_resume_flags_t.save_info_dict.swigValue());
}
/**
* Returns true if this handle refers to a valid torrent and false if it
* hasn't been initialized or if the torrent it refers to has been
* aborted. Note that a handle may become invalid after it has been added
* to the session. Usually this is because the storage for the torrent is
* somehow invalid or if the filenames are not allowed (and hence cannot
* be opened/created) on your filesystem. If such an error occurs, a
* file_error_alert is generated and all handles that refers to that
* torrent will become invalid.
*
* @return
*/
public boolean isValid() {
return th.is_valid();
}
/**
* Generates a magnet URI from the specified torrent. If the torrent
* handle is invalid, null is returned.
*
* @return
*/
public String makeMagnetUri() {
return th.is_valid() ? libtorrent.make_magnet_uri(th) : null;
}
// ``set_upload_limit`` will limit the upload bandwidth used by this
// particular torrent to the limit you set. It is given as the number of
// bytes per second the torrent is allowed to upload.
// ``set_download_limit`` works the same way but for download bandwidth
// instead of upload bandwidth. Note that setting a higher limit on a
// torrent then the global limit
// (``session_settings::upload_rate_limit``) will not override the global
// rate limit. The torrent can never upload more than the global rate
// limit.
//
// ``upload_limit`` and ``download_limit`` will return the current limit
// setting, for upload and download, respectively.
public int getUploadLimit() {
return th.upload_limit();
}
// ``set_upload_limit`` will limit the upload bandwidth used by this
// particular torrent to the limit you set. It is given as the number of
// bytes per second the torrent is allowed to upload.
// ``set_download_limit`` works the same way but for download bandwidth
// instead of upload bandwidth. Note that setting a higher limit on a
// torrent then the global limit
// (``session_settings::upload_rate_limit``) will not override the global
// rate limit. The torrent can never upload more than the global rate
// limit.
//
// ``upload_limit`` and ``download_limit`` will return the current limit
// setting, for upload and download, respectively.
public void setUploadLimit(int limit) {
th.set_upload_limit(limit);
}
// ``set_upload_limit`` will limit the upload bandwidth used by this
// particular torrent to the limit you set. It is given as the number of
// bytes per second the torrent is allowed to upload.
// ``set_download_limit`` works the same way but for download bandwidth
// instead of upload bandwidth. Note that setting a higher limit on a
// torrent then the global limit
// (``session_settings::upload_rate_limit``) will not override the global
// rate limit. The torrent can never upload more than the global rate
// limit.
//
// ``upload_limit`` and ``download_limit`` will return the current limit
// setting, for upload and download, respectively.
public int getDownloadLimit() {
return th.download_limit();
}
// ``set_upload_limit`` will limit the upload bandwidth used by this
// particular torrent to the limit you set. It is given as the number of
// bytes per second the torrent is allowed to upload.
// ``set_download_limit`` works the same way but for download bandwidth
// instead of upload bandwidth. Note that setting a higher limit on a
// torrent then the global limit
// (``session_settings::upload_rate_limit``) will not override the global
// rate limit. The torrent can never upload more than the global rate
// limit.
//
// ``upload_limit`` and ``download_limit`` will return the current limit
// setting, for upload and download, respectively.
public void setDownloadLimit(int limit) {
th.set_download_limit(limit);
}
// ``force_recheck`` puts the torrent back in a state where it assumes to
// have no resume data. All peers will be disconnected and the torrent
// will stop announcing to the tracker. The torrent will be added to the
// checking queue, and will be checked (all the files will be read and
// compared to the piece hashes). Once the check is complete, the torrent
// will start connecting to peers again, as normal.
public void forceRecheck() {
th.force_recheck();
}
// ``force_reannounce()`` will force this torrent to do another tracker
// request, to receive new peers. The ``seconds`` argument specifies how
// many seconds from now to issue the tracker announces.
//
// If the tracker's ``min_interval`` has not passed since the last
// announce, the forced announce will be scheduled to happen immediately
// as the ``min_interval`` expires. This is to honor trackers minimum
// re-announce interval settings.
//
// The ``tracker_index`` argument specifies which tracker to re-announce.
// If set to -1 (which is the default), all trackers are re-announce.
//
public void forceReannounce(int seconds, int tracker_index) {
th.force_reannounce(seconds, tracker_index);
}
// ``force_reannounce()`` will force this torrent to do another tracker
// request, to receive new peers. The ``seconds`` argument specifies how
// many seconds from now to issue the tracker announces.
//
// If the tracker's ``min_interval`` has not passed since the last
// announce, the forced announce will be scheduled to happen immediately
// as the ``min_interval`` expires. This is to honor trackers minimum
// re-announce interval settings.
//
// The ``tracker_index`` argument specifies which tracker to re-announce.
// If set to -1 (which is the default), all trackers are re-announce.
//
public void forceReannounce(int seconds) {
th.force_reannounce(seconds);
}
/**
* Force this torrent to do another tracker
* request, to receive new peers. The ``seconds`` argument specifies how
* many seconds from now to issue the tracker announces.
* <p/>
* If the tracker's ``min_interval`` has not passed since the last
* announce, the forced announce will be scheduled to happen immediately
* as the ``min_interval`` expires. This is to honor trackers minimum
* re-announce interval settings.
* <p/>
* The ``tracker_index`` argument specifies which tracker to re-announce.
* If set to -1 (which is the default), all trackers are re-announce.
*/
public void forceReannounce() {
th.force_reannounce();
}
/**
* Announce the torrent to the DHT immediately.
*/
public void forceDHTAnnounce() {
th.force_dht_announce();
}
/**
* Will return the list of trackers for this torrent. The
* announce entry contains both a string ``url`` which specify the
* announce url for the tracker as well as an int ``tier``, which is
* specifies the order in which this tracker is tried.
*
* @return
*/
public List<AnnounceEntry> getTrackers() {
announce_entry_vector v = th.trackers();
int size = (int) v.size();
List<AnnounceEntry> list = new ArrayList<AnnounceEntry>(size);
for (int i = 0; i < size; i++) {
list.add(new AnnounceEntry(v.get(i)));
}
return list;
}
/**
* Will send a scrape request to the tracker. A
* scrape request queries the tracker for statistics such as total number
* of incomplete peers, complete peers, number of downloads etc.
* <p/>
* This request will specifically update the ``num_complete`` and
* ``num_incomplete`` fields in the torrent_status struct once it
* completes. When it completes, it will generate a scrape_reply_alert.
* If it fails, it will generate a scrape_failed_alert.
*/
public void scrapeTracker() {
th.scrape_tracker();
}
// If you want
// libtorrent to use another list of trackers for this torrent, you can
// use ``replace_trackers()`` which takes a list of the same form as the
// one returned from ``trackers()`` and will replace it. If you want an
// immediate effect, you have to call force_reannounce(). See
// announce_entry.
//
// The updated set of trackers will be saved in the resume data, and when
// a torrent is started with resume data, the trackers from the resume
// data will replace the original ones.
public void replaceTrackers(List<AnnounceEntry> trackers) {
announce_entry_vector v = new announce_entry_vector();
for (AnnounceEntry e : trackers) {
v.add(e.getSwig());
}
th.replace_trackers(v);
}
// ``add_tracker()`` will look if the specified tracker is already in the
// set. If it is, it doesn't do anything. If it's not in the current set
// of trackers, it will insert it in the tier specified in the
// announce_entry.
//
// The updated set of trackers will be saved in the resume data, and when
// a torrent is started with resume data, the trackers from the resume
// data will replace the original ones.
public void addTracker(AnnounceEntry tracker) {
th.add_tracker(tracker.getSwig());
}
// ``add_url_seed()`` adds another url to the torrent's list of url
// seeds. If the given url already exists in that list, the call has no
// effect. The torrent will connect to the server and try to download
// pieces from it, unless it's paused, queued, checking or seeding.
// ``remove_url_seed()`` removes the given url if it exists already.
// ``url_seeds()`` return a set of the url seeds currently in this
// torrent. Note that urls that fails may be removed automatically from
// the list.
//
// See http-seeding_ for more information.
public void addUrlSeed(String url) {
th.add_url_seed(url);
}
// ``add_url_seed()`` adds another url to the torrent's list of url
// seeds. If the given url already exists in that list, the call has no
// effect. The torrent will connect to the server and try to download
// pieces from it, unless it's paused, queued, checking or seeding.
// ``remove_url_seed()`` removes the given url if it exists already.
// ``url_seeds()`` return a set of the url seeds currently in this
// torrent. Note that urls that fails may be removed automatically from
// the list.
//
// See http-seeding_ for more information.
public void removeUrlSeed(String url) {
th.remove_url_seed(url);
}
// These functions are identical as the ``*_url_seed()`` variants, but
// they operate on `BEP 17`_ web seeds instead of `BEP 19`_.
//
// See http-seeding_ for more information.
public void addHttpSeed(String url) {
th.add_url_seed(url);
}
// These functions are identical as the ``*_url_seed()`` variants, but
// they operate on `BEP 17`_ web seeds instead of `BEP 19`_.
//
// See http-seeding_ for more information.
public void removeHttpSeed(String url) {
th.remove_http_seed(url);
}
/**
* index must be in the range [0, number_of_files).
* <p/>
* The priority values are the same as for piece_priority().
* <p/>
* Whenever a file priority is changed, all other piece priorities are
* reset to match the file priorities. In order to maintain sepcial
* priorities for particular pieces, piece_priority() has to be called
* again for those pieces.
* <p/>
* You cannot set the file priorities on a torrent that does not yet have
* metadata or a torrent that is a seed. ``file_priority(int, int)`` and
* prioritize_files() are both no-ops for such torrents.
*
* @param index
* @param priority
*/
public void setFilePriority(int index, Priority priority) {
th.file_priority(index, priority.getSwig());
}
/**
* index must be in the range [0, number_of_files).
* <p/>
* queries or sets the priority of file index.
*
* @param index
* @return
*/
public Priority getFilePriority(int index) {
return Priority.fromSwig(th.file_priority(index));
}
/**
* Takes a vector that has at as many elements as
* there are files in the torrent. Each entry is the priority of that
* file. The function sets the priorities of all the pieces in the
* torrent based on the vector.
*
* @param priorities
*/
public void prioritizeFiles(Priority[] priorities) {
int[] arr = new int[priorities.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = priorities[i] != Priority.UNKNOWN ? priorities[i].getSwig() : Priority.IGNORE.getSwig();
}
th.prioritize_files(Vectors.ints2int_vector(arr));
}
/**
* Returns a vector with the priorities of all files.
*
* @return
*/
public Priority[] getFilePriorities() {
int_vector v = th.file_priorities();
int size = (int) v.size();
Priority[] arr = new Priority[size];
for (int i = 0; i < size; i++) {
arr[i] = Priority.fromSwig(v.get(i));
}
return arr;
}
/**
* This function fills in the supplied vector with the number of
* bytes downloaded of each file in this torrent. The progress values are
* ordered the same as the files in the torrent_info. This operation is
* not very cheap. Its complexity is *O(n + mj)*. Where *n* is the number
* of files, *m* is the number of downloading pieces and *j* is the
* number of blocks in a piece.
* <p/>
* The ``flags`` parameter can be used to specify the granularity of the
* file progress. If left at the default value of 0, the progress will be
* as accurate as possible, but also more expensive to calculate. If
* ``torrent_handle::piece_granularity`` is specified, the progress will
* be specified in piece granularity. i.e. only pieces that have been
* fully downloaded and passed the hash check count. When specifying
* piece granularity, the operation is a lot cheaper, since libtorrent
* already keeps track of this internally and no calculation is required.
*
* @param flags
* @return
*/
public long[] getFileProgress(FileProgressFlags flags) {
int64_vector v = new int64_vector();
th.file_progress(v, flags.getSwig());
return Vectors.int64_vector2longs(v);
}
/**
* This function fills in the supplied vector with the number of
* bytes downloaded of each file in this torrent. The progress values are
* ordered the same as the files in the torrent_info. This operation is
* not very cheap. Its complexity is *O(n + mj)*. Where *n* is the number
* of files, *m* is the number of downloading pieces and *j* is the
* number of blocks in a piece.
*
* @return
*/
public long[] getFileProgress() {
int64_vector v = new int64_vector();
th.file_progress(v);
return Vectors.int64_vector2longs(v);
}
/**
* The path to the directory where this torrent's files are stored.
* It's typically the path as was given to async_add_torrent() or
* add_torrent() when this torrent was started.
*
* @return
*/
public String getSavePath() {
torrent_status ts = th.status(status_flags_t.query_save_path.swigValue());
return ts.getSave_path();
}
/**
* The name of the torrent. Typically this is derived from the
* .torrent file. In case the torrent was started without metadata,
* and hasn't completely received it yet, it returns the name given
* to it when added to the session.
*
* @return
*/
public String getName() {
torrent_status ts = th.status(status_flags_t.query_name.swigValue());
return ts.getName();
}
/**
* flags to be passed in file_progress().
*/
public enum FileProgressFlags {
DEFAULT(0),
/**
* only calculate file progress at piece granularity. This makes
* the file_progress() call cheaper and also only takes bytes that
* have passed the hash check into account, so progress cannot
* regress in this mode.
*/
PIECE_GRANULARITY(torrent_handle.file_progress_flags_t.piece_granularity.swigValue());
private FileProgressFlags(int swigValue) {
this.swigValue = swigValue;
}
private final int swigValue;
public int getSwig() {
return swigValue;
}
}
}