added api for piece priorities

This commit is contained in:
Arvid Norberg 2007-03-20 01:59:00 +00:00
parent 962b2ab015
commit 776b399a97
9 changed files with 731 additions and 414 deletions

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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()
---------------

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;