added api for piece priorities
This commit is contained in:
parent
962b2ab015
commit
776b399a97
|
@ -1,3 +1,12 @@
|
|||
* the following functions have been deprecated:
|
||||
void torrent_handle::filter_piece(int index, bool filter) const;
|
||||
void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const;
|
||||
bool torrent_handle::is_piece_filtered(int index) const;
|
||||
std::vector<bool> torrent_handle::filtered_pieces() const;
|
||||
void torrent_handle::filter_files(std::vector<bool> const& files) const;
|
||||
|
||||
instead, use the piece_priority functions.
|
||||
|
||||
* added support for NAT-PMP
|
||||
* added support for piece priorities. Piece filtering is now set as
|
||||
a priority
|
||||
|
|
772
docs/manual.html
772
docs/manual.html
File diff suppressed because it is too large
Load Diff
|
@ -1217,11 +1217,19 @@ Its declaration looks like this::
|
|||
void resolve_countries(bool r);
|
||||
bool resolve_countries() const;
|
||||
|
||||
void piece_priority(int index, int priority) const;
|
||||
int piece_priority(int index) const;
|
||||
|
||||
void prioritize_pieces(std::vector<int> const& pieces) const;
|
||||
std::vector<int> piece_priorities() const;
|
||||
|
||||
void prioritize_files(std::vector<int> const& files) const;
|
||||
|
||||
// these functions are deprecated
|
||||
void filter_piece(int index, bool filter) const;
|
||||
void filter_pieces(std::vector<bool> const& bitmask) const;
|
||||
bool is_piece_filtered(int index) const;
|
||||
std::vector<bool> filtered_pieces() const;
|
||||
|
||||
void filter_files(std::vector<bool> const& files) const;
|
||||
|
||||
bool has_metadata() const;
|
||||
|
@ -1236,9 +1244,10 @@ Its declaration looks like this::
|
|||
bool operator<(torrent_handle const&) const;
|
||||
};
|
||||
|
||||
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``.
|
||||
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``.
|
||||
|
||||
.. warning:: All operations on a ``torrent_handle`` may throw invalid_handle_
|
||||
exception, in case the handle is no longer refering to a torrent. There are
|
||||
|
@ -1246,7 +1255,54 @@ any operation on an uninitialized handle, it will throw ``invalid_handle``.
|
|||
Since the torrents are processed by a background thread, there is no
|
||||
guarantee that a handle will remain valid between two calls.
|
||||
|
||||
*TODO: document filter_piece(), filter_pieces(), is_piece_filtered(), filtered_pieces() and filter_files()*
|
||||
|
||||
piece_priority() prioritize_pieces() piece_priorities() prioritize_files()
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
void piece_priority(int index, int priority) const;
|
||||
int piece_priority(int index) const;
|
||||
void prioritize_pieces(std::vector<int> const& pieces) const;
|
||||
std::vector<int> piece_priorities() const;
|
||||
void prioritize_files(std::vector<int> const& files) const;
|
||||
|
||||
These functions are used to set and get the prioritiy of individual pieces.
|
||||
By default all pieces have priority 1. That means that the random rarest
|
||||
first algorithm is effectively active for all pieces. You may however
|
||||
change the priority of individual pieces. There are 8 different priority
|
||||
levels:
|
||||
|
||||
0. piece is not downloaded at all
|
||||
1. normal priority. Download order is dependent on availability
|
||||
2. higher than normal priority. Pieces are preferred over pieces with
|
||||
the same availability, but not over pieces with lower availability
|
||||
3. pieces are as likely to be picked as partial pieces.
|
||||
4. pieces are preferred over partial pieces, but not over pieces with
|
||||
lower availability
|
||||
5. *currently the same as 4*
|
||||
6. piece is as likely to be picked as any piece with availability 1
|
||||
7. maximum priority, availability is disregarded, the piece is preferred
|
||||
over any other piece with lower priority
|
||||
|
||||
The exact definitions of these priorities are implementation details, and
|
||||
subject to change. The interface guarantees that higher number means higher
|
||||
priority, and that 0 means do not download.
|
||||
|
||||
``piece_priority`` sets or gets the priority for an individual piece,
|
||||
specified by ``index``.
|
||||
|
||||
``prioritize_pieces`` takes a vector of integers, one integer per piece in
|
||||
the torrent. All the piece priorities will be updated with the priorities
|
||||
in the vector.
|
||||
|
||||
``piece_priorities`` returns a vector with one element for each piece in the
|
||||
torrent. Each element is the current priority of that piece.
|
||||
|
||||
``prioritize_files`` 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.
|
||||
|
||||
|
||||
file_progress()
|
||||
---------------
|
||||
|
|
|
@ -138,18 +138,21 @@ namespace libtorrent
|
|||
void we_have(int index);
|
||||
|
||||
// sets the priority of a piece.
|
||||
// 0 is filtered, i.e. do not download
|
||||
// 1 is normal priority
|
||||
// 2 is high priority
|
||||
// 3 is maximum priority (availability is ignored)
|
||||
void set_piece_priority(int index, int prio);
|
||||
|
||||
// returns the priority for the piece at 'index'
|
||||
int piece_priority(int index) const;
|
||||
|
||||
// returns the current piece priorities for all pieces
|
||||
void piece_priorities(std::vector<int>& pieces) const;
|
||||
|
||||
// ========== start deprecation ==============
|
||||
|
||||
// fills the bitmask with 1's for pieces that are filtered
|
||||
void filtered_pieces(std::vector<bool>& mask) const;
|
||||
|
||||
// ========== end deprecation ==============
|
||||
|
||||
// pieces should be the vector that represents the pieces a
|
||||
// client has. It returns a list of all pieces that this client
|
||||
// has and that are interesting to download. It returns them in
|
||||
|
@ -245,18 +248,21 @@ namespace libtorrent
|
|||
unsigned downloading : 1;
|
||||
// is 0 if the piece is filtered (not to be downloaded)
|
||||
// 1 is normal priority (default)
|
||||
// 2 is high priority
|
||||
// 3 is maximum priority (ignores availability)
|
||||
unsigned piece_priority : 2;
|
||||
// 2 is higher priority than pieces at the same availability level
|
||||
// 3 is same priority as partial pieces
|
||||
// 4 is higher priority than partial pieces
|
||||
// 5 and 6 same priority as availability 1 (ignores availability)
|
||||
// 7 is maximum priority (ignores availability)
|
||||
unsigned piece_priority : 3;
|
||||
// index in to the piece_info vector
|
||||
unsigned index : 19;
|
||||
unsigned index : 18;
|
||||
|
||||
enum
|
||||
{
|
||||
// index is set to this to indicate that we have the
|
||||
// piece. There is no entry for the piece in the
|
||||
// buckets if this is the case.
|
||||
we_have_index = 0x7ffff,
|
||||
we_have_index = 0x3ffff,
|
||||
// the priority value that means the piece is filtered
|
||||
filter_priority = 0,
|
||||
// the max number the peer count can hold
|
||||
|
@ -281,7 +287,11 @@ namespace libtorrent
|
|||
switch (piece_priority)
|
||||
{
|
||||
case 2: return prio - 1;
|
||||
case 3: return 1;
|
||||
case 3: return (std::max)(prio / 2, 1);
|
||||
case 4: return (std::max)(prio / 2 - 1, 1);
|
||||
case 5:
|
||||
case 6: return (std::min)(prio / 2 - 1, 2);
|
||||
case 7: return 1;
|
||||
}
|
||||
return prio;
|
||||
}
|
||||
|
|
|
@ -171,12 +171,23 @@ namespace libtorrent
|
|||
void resume();
|
||||
bool is_paused() const { return m_paused; }
|
||||
|
||||
// ============ start deprecation =============
|
||||
void filter_piece(int index, bool filter);
|
||||
void filter_pieces(std::vector<bool> const& bitmask);
|
||||
bool is_piece_filtered(int index) const;
|
||||
void filtered_pieces(std::vector<bool>& bitmask) const;
|
||||
|
||||
void filter_files(std::vector<bool> const& files);
|
||||
// ============ end deprecation =============
|
||||
|
||||
|
||||
void set_piece_priority(int index, int priority);
|
||||
int piece_priority(int index) const;
|
||||
|
||||
void prioritize_pieces(std::vector<int> const& pieces);
|
||||
void piece_priorities(std::vector<int>&) const;
|
||||
|
||||
void prioritize_files(std::vector<int> const& files);
|
||||
|
||||
|
||||
torrent_status status() const;
|
||||
void file_progress(std::vector<float>& fp) const;
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace libtorrent
|
|||
// the number of distributed copies of the file.
|
||||
// note that one copy may be spread out among many peers.
|
||||
//
|
||||
// the whole number part tells how many copies
|
||||
// the integer part tells how many copies
|
||||
// there are of the rarest piece(s)
|
||||
//
|
||||
// the fractional part tells the fraction of pieces that
|
||||
|
@ -247,17 +247,33 @@ namespace libtorrent
|
|||
void resolve_countries(bool r);
|
||||
bool resolve_countries() const;
|
||||
|
||||
// all these are deprecated, use piece
|
||||
// priority functions instead
|
||||
|
||||
// ================ start deprecation ============
|
||||
|
||||
// marks the piece with the given index as filtered
|
||||
// it will not be downloaded
|
||||
void filter_piece(int index, bool filter) const;
|
||||
void filter_pieces(std::vector<bool> const& pieces) const;
|
||||
bool is_piece_filtered(int index) const;
|
||||
std::vector<bool> filtered_pieces() const;
|
||||
|
||||
// marks the file with the given index as filtered
|
||||
// it will not be downloaded
|
||||
void filter_files(std::vector<bool> const& files) const;
|
||||
|
||||
// ================ end deprecation ============
|
||||
|
||||
// priority must be within the range [0, 7]
|
||||
void piece_priority(int index, int priority) const;
|
||||
int piece_priority(int index) const;
|
||||
|
||||
void prioritize_pieces(std::vector<int> const& pieces) const;
|
||||
std::vector<int> piece_priorities() const;
|
||||
|
||||
void prioritize_files(std::vector<int> const& files) const;
|
||||
|
||||
|
||||
// set the interface to bind outgoing connections
|
||||
// to.
|
||||
void use_interface(const char* net_interface) const;
|
||||
|
|
|
@ -649,7 +649,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
assert(new_piece_priority >= 0);
|
||||
assert(new_piece_priority <= 3);
|
||||
assert(new_piece_priority <= 7);
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_piece_map.size());
|
||||
|
||||
|
@ -701,34 +701,7 @@ namespace libtorrent
|
|||
move(prev_priority, p.index);
|
||||
}
|
||||
}
|
||||
/*
|
||||
// this function can be used for pieces that we don't
|
||||
// have, but have marked as filtered (so we didn't
|
||||
// want to download them) but later want to enable for
|
||||
// downloading, then we call this function and it will
|
||||
// be inserted in the available piece list again
|
||||
void piece_picker::mark_as_unfiltered(int index)
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_piece_map.size());
|
||||
|
||||
piece_pos& p = m_piece_map[index];
|
||||
if (!p.filtered()) return;
|
||||
p.filtered(false);
|
||||
if (p.index != piece_pos::we_have_index)
|
||||
{
|
||||
--m_num_filtered;
|
||||
assert(m_num_filtered >= 0);
|
||||
add(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
--m_num_have_filtered;
|
||||
assert(m_num_have_filtered >= 0);
|
||||
}
|
||||
}
|
||||
*/
|
||||
int piece_picker::piece_priority(int index) const
|
||||
{
|
||||
assert(index >= 0);
|
||||
|
@ -737,6 +710,19 @@ namespace libtorrent
|
|||
return m_piece_map[index].piece_priority;
|
||||
}
|
||||
|
||||
void piece_picker::piece_priorities(std::vector<int>& pieces) const
|
||||
{
|
||||
pieces.resize(m_piece_map.size());
|
||||
std::vector<int>::iterator j = pieces.begin();
|
||||
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin(),
|
||||
end(m_piece_map.end()); i != end; ++i, ++j)
|
||||
{
|
||||
*j = i->piece_priority;
|
||||
}
|
||||
}
|
||||
|
||||
// ============ start deprecation ==============
|
||||
|
||||
void piece_picker::filtered_pieces(std::vector<bool>& mask) const
|
||||
{
|
||||
mask.resize(m_piece_map.size());
|
||||
|
@ -748,6 +734,8 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// ============ end deprecation ==============
|
||||
|
||||
void piece_picker::pick_pieces(const std::vector<bool>& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
|
|
128
src/torrent.cpp
128
src/torrent.cpp
|
@ -1022,6 +1022,134 @@ namespace libtorrent
|
|||
return m_username + ":" + m_password;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void torrent::set_piece_priority(int index, int priority)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(valid_metadata());
|
||||
if (is_seed()) return;
|
||||
|
||||
// this call is only valid on torrents with metadata
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
|
||||
// TODO: update peer's interesting-bit
|
||||
|
||||
m_picker->set_piece_priority(index, priority);
|
||||
}
|
||||
|
||||
int torrent::piece_priority(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(valid_metadata());
|
||||
if (is_seed()) return 1;
|
||||
|
||||
// this call is only valid on torrents with metadata
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
|
||||
// TODO: update peer's interesting-bit
|
||||
|
||||
return m_picker->piece_priority(index);
|
||||
}
|
||||
|
||||
void torrent::prioritize_pieces(std::vector<int> const& pieces)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// this call is only valid on torrents with metadata
|
||||
assert(valid_metadata());
|
||||
if (is_seed()) return;
|
||||
|
||||
assert(m_picker.get());
|
||||
|
||||
// TODO: update peer's interesting-bit
|
||||
|
||||
int index = 0;
|
||||
for (std::vector<int>::const_iterator i = pieces.begin()
|
||||
, end(pieces.end()); i != end; ++i, ++index)
|
||||
{
|
||||
assert(*i >= 0);
|
||||
assert(*i <= 7);
|
||||
m_picker->set_piece_priority(index, *i);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::piece_priorities(std::vector<int>& pieces) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// this call is only valid on torrents with metadata
|
||||
assert(valid_metadata());
|
||||
if (is_seed())
|
||||
{
|
||||
pieces.clear();
|
||||
pieces.resize(m_torrent_file.num_pieces(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_picker.get());
|
||||
m_picker->piece_priorities(pieces);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void set_if_greater(int& piece_prio, int file_prio)
|
||||
{
|
||||
if (file_prio > piece_prio) piece_prio = file_prio;
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::prioritize_files(std::vector<int> const& files)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// this call is only valid on torrents with metadata
|
||||
if (!valid_metadata() || is_seed()) return;
|
||||
|
||||
// the bitmask need to have exactly one bit for every file
|
||||
// in the torrent
|
||||
assert(int(files.size()) == m_torrent_file.num_files());
|
||||
|
||||
size_type position = 0;
|
||||
|
||||
if (m_torrent_file.num_pieces())
|
||||
{
|
||||
int piece_length = m_torrent_file.piece_length();
|
||||
// initialize the piece priorities to 0, then only allow
|
||||
// setting higher priorities
|
||||
std::vector<int> pieces(m_torrent_file.num_pieces(), 0);
|
||||
for (int i = 0; i < int(files.size()); ++i)
|
||||
{
|
||||
size_type start = position;
|
||||
position += m_torrent_file.file_at(i).size;
|
||||
// mark all pieces of the file with this file's priority
|
||||
// but only if the priority is higher than the pieces
|
||||
// already set (to avoid problems with overlapping pieces)
|
||||
int start_piece = int(start / piece_length);
|
||||
int last_piece = int(position / piece_length);
|
||||
// if one piece spans several files, we might
|
||||
// come here several times with the same start_piece, end_piece
|
||||
std::for_each(pieces.begin() + start_piece
|
||||
, pieces.begin() + last_piece + 1
|
||||
, bind(&set_if_greater, _1, files[i]));
|
||||
}
|
||||
prioritize_pieces(pieces);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void torrent::filter_piece(int index, bool filter)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
|
@ -330,6 +330,57 @@ namespace libtorrent
|
|||
, bind(&torrent::set_sequenced_download_threshold, _1, threshold));
|
||||
}
|
||||
|
||||
std::string torrent_handle::name() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
return call_member<std::string>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::name, _1));
|
||||
}
|
||||
|
||||
|
||||
void torrent_handle::piece_priority(int index, int priority) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
call_member<void>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::set_piece_priority, _1, index, priority));
|
||||
}
|
||||
|
||||
int torrent_handle::piece_priority(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
return call_member<int>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::piece_priority, _1, index));
|
||||
}
|
||||
|
||||
void torrent_handle::prioritize_pieces(std::vector<int> const& pieces) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
call_member<void>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::prioritize_pieces, _1, boost::cref(pieces)));
|
||||
}
|
||||
|
||||
std::vector<int> torrent_handle::piece_priorities() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
std::vector<int> ret;
|
||||
call_member<void>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::piece_priorities, _1, boost::ref(ret)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void torrent_handle::prioritize_files(std::vector<int> const& files) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
call_member<void>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::prioritize_files, _1, boost::cref(files)));
|
||||
}
|
||||
|
||||
// ============ start deprecation ===============
|
||||
|
||||
void torrent_handle::filter_piece(int index, bool filter) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -341,7 +392,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
call_member<void>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::filter_pieces, _1, pieces));
|
||||
, bind(&torrent::filter_pieces, _1, boost::cref(pieces)));
|
||||
}
|
||||
|
||||
bool torrent_handle::is_piece_filtered(int index) const
|
||||
|
@ -351,13 +402,6 @@ namespace libtorrent
|
|||
, bind(&torrent::is_piece_filtered, _1, index));
|
||||
}
|
||||
|
||||
std::string torrent_handle::name() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
return call_member<std::string>(m_ses, m_chk, m_info_hash
|
||||
, bind(&torrent::name, _1));
|
||||
}
|
||||
|
||||
std::vector<bool> torrent_handle::filtered_pieces() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -374,6 +418,9 @@ namespace libtorrent
|
|||
, bind(&torrent::filter_files, _1, files));
|
||||
}
|
||||
|
||||
// ============ end deprecation ===============
|
||||
|
||||
|
||||
std::vector<announce_entry> const& torrent_handle::trackers() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
Loading…
Reference in New Issue