rewrote the piece picker to be more cpu and memory efficient. replaces the concept of sequential-download-threshold with just a sequential download settings
This commit is contained in:
@@ -133,7 +133,8 @@ namespace libtorrent
|
||||
|
||||
void get_availability(std::vector<int>& avail) const;
|
||||
|
||||
void set_sequenced_download_threshold(int sequenced_download_threshold);
|
||||
void sequential_download(bool sd);
|
||||
bool sequential_download() const { return m_sequential_download >= 0; }
|
||||
|
||||
// the vector tells which pieces we already have
|
||||
// and which we don't have.
|
||||
@@ -143,12 +144,16 @@ namespace libtorrent
|
||||
, std::vector<int>& verify_pieces);
|
||||
|
||||
// increases the peer count for the given piece
|
||||
// (is used when a HAVE or BITFIELD message is received)
|
||||
// (is used when a HAVE message is received)
|
||||
void inc_refcount(int index);
|
||||
void dec_refcount(int index);
|
||||
|
||||
// increases the peer count for the given piece
|
||||
// (is used when a BITFIELD message is received)
|
||||
void inc_refcount(std::vector<bool> const& bitmask);
|
||||
// decreases the peer count for the given piece
|
||||
// (used when a peer disconnects)
|
||||
void dec_refcount(int index);
|
||||
void dec_refcount(std::vector<bool> const& bitmask);
|
||||
|
||||
// these will increase and decrease the peer count
|
||||
// of all pieces. They are used when seeds join
|
||||
@@ -274,9 +279,11 @@ namespace libtorrent
|
||||
|
||||
#ifndef NDEBUG
|
||||
// used in debug mode
|
||||
void verify_priority(int start, int end, int prio) const;
|
||||
void check_invariant(const torrent* t = 0) const;
|
||||
void verify_pick(std::vector<piece_block> const& picked
|
||||
, std::vector<bool> const& bitfield) const;
|
||||
void print_pieces() const;
|
||||
#endif
|
||||
|
||||
// functor that compares indices on downloading_pieces
|
||||
@@ -295,6 +302,8 @@ namespace libtorrent
|
||||
|
||||
private:
|
||||
|
||||
friend struct piece_pos;
|
||||
|
||||
bool can_pick(int piece, std::vector<bool> const& bitmask) const;
|
||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const;
|
||||
@@ -346,26 +355,20 @@ namespace libtorrent
|
||||
bool filtered() const { return piece_priority == filter_priority; }
|
||||
void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
|
||||
|
||||
int priority(int limit) const
|
||||
int priority(piece_picker const* picker) const
|
||||
{
|
||||
if (downloading || filtered() || have()) return 0;
|
||||
if (downloading || filtered()
|
||||
|| have() || peer_count + picker->m_seeds == 0)
|
||||
return -1;
|
||||
|
||||
// priority 5, 6 and 7 disregards availability of the piece
|
||||
if (piece_priority > 4) return 7 - piece_priority;
|
||||
|
||||
// pieces we are currently downloading have high priority
|
||||
int prio = peer_count * 2;
|
||||
// if the peer_count is 0 or 1, the priority cannot be higher
|
||||
if (prio <= 1) return prio;
|
||||
if (prio >= limit * 2) prio = limit * 2;
|
||||
// the different priority levels
|
||||
switch (piece_priority)
|
||||
{
|
||||
case 1: return prio;
|
||||
case 2: return prio - 1;
|
||||
case 3: return (std::max)(prio / 2, 1);
|
||||
case 4: return (std::max)(prio / 2 - 1, 1);
|
||||
case 5: return (std::max)(prio / 3, 1);
|
||||
case 6: return (std::max)(prio / 3 - 1, 1);
|
||||
case 7: return 1;
|
||||
}
|
||||
return prio;
|
||||
int prio = peer_count * 4;
|
||||
// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6;
|
||||
|
||||
return prio + (4 - piece_priority);
|
||||
}
|
||||
|
||||
bool operator!=(piece_pos p) const
|
||||
@@ -378,27 +381,44 @@ namespace libtorrent
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4);
|
||||
|
||||
bool is_ordered(int priority) const
|
||||
{
|
||||
return priority >= m_sequenced_download_threshold * 2;
|
||||
}
|
||||
void update_pieces() const;
|
||||
|
||||
// fills in the range [start, end) of pieces in
|
||||
// m_pieces that have priority 'prio'
|
||||
void priority_range(int prio, int* start, int* end);
|
||||
|
||||
// adds the piece 'index' to m_pieces
|
||||
void add(int index);
|
||||
void move(int vec_index, int elem_index);
|
||||
// removes the piece with the given priority and the
|
||||
// elem_index in the m_pieces vector
|
||||
void remove(int priority, int elem_index);
|
||||
// updates the position of the piece with the given
|
||||
// priority and the elem_index in the m_pieces vector
|
||||
void update(int priority, int elem_index);
|
||||
// shuffles the given piece inside it's priority range
|
||||
void shuffle(int priority, int elem_index);
|
||||
|
||||
void sort_piece(std::vector<downloading_piece>::iterator dp);
|
||||
|
||||
downloading_piece& add_download_piece();
|
||||
void erase_download_piece(std::vector<downloading_piece>::iterator i);
|
||||
|
||||
// this vector contains all pieces we don't have.
|
||||
// in the first entry (index 0) is a vector of all pieces
|
||||
// that no peer have, the vector at index 1 contains
|
||||
// all pieces that exactly one peer have, index 2 contains
|
||||
// all pieces exactly two peers have and so on.
|
||||
// this is not entirely true. The availibility of a piece
|
||||
// is adjusted depending on its priority. But the principle
|
||||
// is that the higher index, the lower priority a piece has.
|
||||
std::vector<std::vector<int> > m_piece_info;
|
||||
// the number of seeds. These are not added to
|
||||
// the availability counters of the pieces
|
||||
int m_seeds;
|
||||
|
||||
// the following vectors are mutable because they sometimes may
|
||||
// be updated lazily, triggered by const functions
|
||||
|
||||
// this vector contains all piece indices that are pickable
|
||||
// sorted by priority. Pieces are in random random order
|
||||
// among pieces with the same priority
|
||||
mutable std::vector<int> m_pieces;
|
||||
|
||||
// these are indices to the priority boundries inside
|
||||
// the m_pieces vector. priority 0 always start at
|
||||
// 0, priority 1 starts at m_priority_boundries[0] etc.
|
||||
mutable std::vector<int> m_priority_boundries;
|
||||
|
||||
// this maps indices to number of peers that has this piece and
|
||||
// index into the m_piece_info vectors.
|
||||
@@ -406,7 +426,7 @@ namespace libtorrent
|
||||
// doesn't exist in the piece_info buckets
|
||||
// pieces with the filtered flag set doesn't have entries in
|
||||
// the m_piece_info buckets either
|
||||
std::vector<piece_pos> m_piece_map;
|
||||
mutable std::vector<piece_pos> m_piece_map;
|
||||
|
||||
// each piece that's currently being downloaded
|
||||
// has an entry in this list with block allocations.
|
||||
@@ -438,9 +458,16 @@ namespace libtorrent
|
||||
// the number of pieces we have
|
||||
int m_num_have;
|
||||
|
||||
// the required popularity of a piece in order to download
|
||||
// it in sequence instead of random order.
|
||||
int m_sequenced_download_threshold;
|
||||
// -1 means sequential download is not active.
|
||||
// >= 0 means that pieces are requested in sequential order
|
||||
// and this variable is the next piece to request.
|
||||
// in that case m_pieces is cleared and not used.
|
||||
int m_sequential_download;
|
||||
|
||||
// if this is set to true, it means update_pieces()
|
||||
// has to be called before accessing m_pieces.
|
||||
mutable bool m_dirty;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool m_files_checked_called;
|
||||
#endif
|
||||
|
@@ -157,7 +157,7 @@ namespace libtorrent
|
||||
|
||||
aux::session_impl& session() { return m_ses; }
|
||||
|
||||
void set_sequenced_download_threshold(int threshold);
|
||||
void set_sequential_download(bool sd);
|
||||
|
||||
bool verify_resume_data(entry& rd, std::string& error)
|
||||
{ TORRENT_ASSERT(m_storage); return m_storage->verify_resume_data(rd, error); }
|
||||
@@ -371,8 +371,7 @@ namespace libtorrent
|
||||
|
||||
int num_pieces() const { return m_num_pieces; }
|
||||
|
||||
// when we get a have- or bitfield- messages, this is called for every
|
||||
// piece a peer has gained.
|
||||
// when we get a have message, this is called for that piece
|
||||
void peer_has(int index)
|
||||
{
|
||||
if (m_picker.get())
|
||||
@@ -389,6 +388,22 @@ namespace libtorrent
|
||||
#endif
|
||||
}
|
||||
|
||||
// when we get a bitfield message, this is called for that piece
|
||||
void peer_has(std::vector<bool> const& bitfield)
|
||||
{
|
||||
if (m_picker.get())
|
||||
{
|
||||
TORRENT_ASSERT(!is_seed());
|
||||
m_picker->inc_refcount(bitfield);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
else
|
||||
{
|
||||
TORRENT_ASSERT(is_seed());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void peer_has_all()
|
||||
{
|
||||
if (m_picker.get())
|
||||
@@ -404,7 +419,6 @@ namespace libtorrent
|
||||
#endif
|
||||
}
|
||||
|
||||
// when peer disconnects, this is called for every piece it had
|
||||
void peer_lost(int index)
|
||||
{
|
||||
if (m_picker.get())
|
||||
@@ -725,7 +739,7 @@ namespace libtorrent
|
||||
// in case the piece picker hasn't been constructed
|
||||
// when this settings is set, this variable will keep
|
||||
// its value until the piece picker is created
|
||||
int m_sequenced_download_threshold;
|
||||
bool m_sequential_download;
|
||||
|
||||
// is false by default and set to
|
||||
// true when the first tracker reponse
|
||||
|
@@ -378,7 +378,7 @@ namespace libtorrent
|
||||
void set_download_limit(int limit) const;
|
||||
int download_limit() const;
|
||||
|
||||
void set_sequenced_download_threshold(int threshold) const;
|
||||
void set_sequential_download(bool sd) const;
|
||||
|
||||
void set_peer_upload_limit(tcp::endpoint ip, int limit) const;
|
||||
void set_peer_download_limit(tcp::endpoint ip, int limit) const;
|
||||
|
Reference in New Issue
Block a user