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:
@@ -1,3 +1,5 @@
|
||||
* New, more memory efficient, piece picker with sequential download
|
||||
support (instead of the more complicated sequential download threshold).
|
||||
* Auto Upload slots. Automtically opens up more slots if
|
||||
upload limit is not met.
|
||||
* Improved NAT-PMP support by querying the default gateway (no
|
||||
|
@@ -1427,7 +1427,7 @@ Its declaration looks like this::
|
||||
int upload_limit() const;
|
||||
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(asio::ip::tcp::endpoint ip, int limit) const;
|
||||
void set_peer_download_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
||||
@@ -1658,24 +1658,18 @@ limit.
|
||||
download, respectively.
|
||||
|
||||
|
||||
set_sequenced_download_threshold()
|
||||
----------------------------------
|
||||
set_sequential_download()
|
||||
-------------------------
|
||||
|
||||
::
|
||||
|
||||
void set_sequenced_download_threshold(int threshold);
|
||||
void set_sequential_download(bool sd);
|
||||
|
||||
sequenced-download threshold is the limit on how popular a piece has to be
|
||||
(popular == inverse of rarity) to be downloaded in sequence instead of in
|
||||
random (rarest first) order. It can be used to tweak disk performance in
|
||||
settings where the random download property is less necessary. For example, if
|
||||
the threshold is 10, all pieces which 10 or more peers have, will be downloaded
|
||||
in index order. This setting defaults to 100, which means that it is disabled
|
||||
in practice.
|
||||
Enables or disables *sequential download*. When enabled, the piece picker will pick pieces in sequence
|
||||
instead of rarest first.
|
||||
|
||||
Setting this threshold to a very small value will affect the piece distribution
|
||||
negatively in the swarm. It should basically only be used in situations where
|
||||
the random seeks on the disk is the download bottleneck.
|
||||
Enabling sequential download will affect the piece distribution negatively in the swarm. It should be
|
||||
used sparingly.
|
||||
|
||||
|
||||
set_peer_upload_limit() set_peer_download_limit()
|
||||
|
@@ -476,7 +476,6 @@ void add_torrent(libtorrent::session& ses
|
||||
h.set_max_connections(50);
|
||||
h.set_max_uploads(-1);
|
||||
h.set_ratio(preferred_ratio);
|
||||
h.set_sequenced_download_threshold(15);
|
||||
h.set_upload_limit(torrent_upload_limit);
|
||||
h.set_download_limit(torrent_download_limit);
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
@@ -860,7 +859,6 @@ int main(int ac, char* av[])
|
||||
h.set_max_connections(50);
|
||||
h.set_max_uploads(-1);
|
||||
h.set_ratio(preferred_ratio);
|
||||
h.set_sequenced_download_threshold(15);
|
||||
h.set_upload_limit(torrent_upload_limit);
|
||||
h.set_download_limit(torrent_download_limit);
|
||||
continue;
|
||||
@@ -878,7 +876,6 @@ int main(int ac, char* av[])
|
||||
h.set_max_connections(50);
|
||||
h.set_max_uploads(-1);
|
||||
h.set_ratio(preferred_ratio);
|
||||
h.set_sequenced_download_threshold(15);
|
||||
h.set_upload_limit(torrent_upload_limit);
|
||||
h.set_download_limit(torrent_download_limit);
|
||||
continue;
|
||||
@@ -903,6 +900,7 @@ int main(int ac, char* av[])
|
||||
bool print_downloads = false;
|
||||
bool print_piece_bar = false;
|
||||
bool print_file_progress = false;
|
||||
bool sequential_download = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -930,7 +928,7 @@ int main(int ac, char* av[])
|
||||
break;
|
||||
}
|
||||
|
||||
if(c == 'r')
|
||||
if (c == 'r')
|
||||
{
|
||||
// force reannounce on all torrents
|
||||
std::for_each(handles.begin(), handles.end()
|
||||
@@ -938,7 +936,16 @@ int main(int ac, char* av[])
|
||||
, bind(&handles_t::value_type::second, _1)));
|
||||
}
|
||||
|
||||
if(c == 'p')
|
||||
if (c == 's')
|
||||
{
|
||||
// toggle torrents between sequential and rarest first mode
|
||||
sequential_download = !sequential_download;
|
||||
std::for_each(handles.begin(), handles.end()
|
||||
, bind(&torrent_handle::set_sequential_download
|
||||
, bind(&handles_t::value_type::second, _1), sequential_download));
|
||||
}
|
||||
|
||||
if (c == 'p')
|
||||
{
|
||||
// pause all torrents
|
||||
std::for_each(handles.begin(), handles.end()
|
||||
@@ -946,7 +953,7 @@ int main(int ac, char* av[])
|
||||
, bind(&handles_t::value_type::second, _1)));
|
||||
}
|
||||
|
||||
if(c == 'u')
|
||||
if (c == 'u')
|
||||
{
|
||||
// unpause all torrents
|
||||
std::for_each(handles.begin(), handles.end()
|
||||
|
@@ -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;
|
||||
|
@@ -349,10 +349,12 @@ namespace libtorrent
|
||||
m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all);
|
||||
|
||||
// now that we have a piece_picker,
|
||||
// update it with this peers pieces
|
||||
// update it with this peer's pieces
|
||||
|
||||
int num_pieces = std::count(m_have_piece.begin(), m_have_piece.end(), true);
|
||||
if (num_pieces == int(m_have_piece.size()))
|
||||
TORRENT_ASSERT(m_num_pieces == std::count(m_have_piece.begin()
|
||||
, m_have_piece.end(), true));
|
||||
|
||||
if (m_num_pieces == int(m_have_piece.size()))
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << " *** THIS IS A SEED ***\n";
|
||||
@@ -365,23 +367,21 @@ namespace libtorrent
|
||||
disconnect("seed to seed connection redundant");
|
||||
return;
|
||||
}
|
||||
m_num_pieces = num_pieces;
|
||||
t->peer_has_all();
|
||||
if (!t->is_finished())
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
m_num_pieces = num_pieces;
|
||||
// if we're a seed, we don't keep track of piece availability
|
||||
if (!t->is_seed())
|
||||
{
|
||||
t->peer_has(m_have_piece);
|
||||
bool interesting = false;
|
||||
for (int i = 0; i < int(m_have_piece.size()); ++i)
|
||||
{
|
||||
if (m_have_piece[i])
|
||||
{
|
||||
t->peer_has(i);
|
||||
// if the peer has a piece and we don't, the peer is interesting
|
||||
if (!t->have_piece(i)
|
||||
&& t->picker().piece_priority(i) != 0)
|
||||
@@ -627,7 +627,19 @@ namespace libtorrent
|
||||
TORRENT_ASSERT(m_torrent.expired());
|
||||
// check to make sure we don't have another connection with the same
|
||||
// info_hash and peer_id. If we do. close this connection.
|
||||
#ifndef NDEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
t->attach_peer(this);
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
TORRENT_ASSERT(false);
|
||||
}
|
||||
#endif
|
||||
if (m_disconnecting) return;
|
||||
m_torrent = wpt;
|
||||
|
||||
@@ -1091,50 +1103,32 @@ namespace libtorrent
|
||||
// let the torrent know which pieces the
|
||||
// peer has
|
||||
// if we're a seed, we don't keep track of piece availability
|
||||
bool interesting = false;
|
||||
if (!t->is_seed())
|
||||
{
|
||||
bool interesting = false;
|
||||
t->peer_has(bitfield);
|
||||
|
||||
for (int i = 0; i < (int)m_have_piece.size(); ++i)
|
||||
{
|
||||
bool have = bitfield[i];
|
||||
if (have && !m_have_piece[i])
|
||||
{
|
||||
m_have_piece[i] = true;
|
||||
++m_num_pieces;
|
||||
t->peer_has(i);
|
||||
if (!t->have_piece(i) && t->picker().piece_priority(i) != 0)
|
||||
interesting = true;
|
||||
}
|
||||
else if (!have && m_have_piece[i])
|
||||
{
|
||||
// this should probably not be allowed
|
||||
m_have_piece[i] = false;
|
||||
--m_num_pieces;
|
||||
t->peer_lost(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_have_piece = bitfield;
|
||||
m_num_pieces = num_pieces;
|
||||
|
||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < (int)m_have_piece.size(); ++i)
|
||||
{
|
||||
bool have = bitfield[i];
|
||||
if (have && !m_have_piece[i])
|
||||
{
|
||||
m_have_piece[i] = true;
|
||||
++m_num_pieces;
|
||||
}
|
||||
else if (!have && m_have_piece[i])
|
||||
{
|
||||
// this should probably not be allowed
|
||||
m_have_piece[i] = false;
|
||||
--m_num_pieces;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// ---------- REQUEST ----------
|
||||
@@ -1337,8 +1331,10 @@ namespace libtorrent
|
||||
|
||||
#ifndef NDEBUG
|
||||
check_postcondition post_checker_(t);
|
||||
#if !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
t->check_invariant();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
@@ -1450,7 +1446,7 @@ namespace libtorrent
|
||||
m_outstanding_writing_bytes += p.length;
|
||||
TORRENT_ASSERT(!m_channel_state[download_channel] != peer_info::bw_network);
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
#ifndef NDEBUG
|
||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
t->check_invariant();
|
||||
#endif
|
||||
}
|
||||
@@ -2097,6 +2093,14 @@ namespace libtorrent
|
||||
m_torrent.reset();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// since this connection doesn't have a torrent reference
|
||||
// no torrent should have a reference to this connection either
|
||||
for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin()
|
||||
, end(m_ses.m_torrents.end()); i != end; ++i)
|
||||
TORRENT_ASSERT(!i->second->has_peer(this));
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<socket_type> sock = m_socket;
|
||||
m_disconnecting = true;
|
||||
m_ses.close_connection(this, message);
|
||||
@@ -3013,12 +3017,13 @@ namespace libtorrent
|
||||
#ifndef NDEBUG
|
||||
void peer_connection::check_invariant() const
|
||||
{
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (m_disconnecting)
|
||||
{
|
||||
for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin()
|
||||
, end(m_ses.m_torrents.end()); i != end; ++i)
|
||||
TORRENT_ASSERT(!i->second->has_peer((peer_connection*)this));
|
||||
TORRENT_ASSERT(!m_torrent.lock());
|
||||
TORRENT_ASSERT(!t);
|
||||
}
|
||||
else if (!m_in_constructor)
|
||||
{
|
||||
@@ -3053,8 +3058,15 @@ namespace libtorrent
|
||||
TORRENT_ASSERT(!is_choked());
|
||||
}
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t) return;
|
||||
if (!t)
|
||||
{
|
||||
// since this connection doesn't have a torrent reference
|
||||
// no torrent should have a reference to this connection either
|
||||
for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin()
|
||||
, end(m_ses.m_torrents.end()); i != end; ++i)
|
||||
TORRENT_ASSERT(!i->second->has_peer((peer_connection*)this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_peer_info)
|
||||
{
|
||||
@@ -3208,7 +3220,7 @@ namespace libtorrent
|
||||
time_duration time_limit = seconds(
|
||||
m_ses.settings().inactivity_timeout);
|
||||
|
||||
// don't bother disconnect peers we haven't been intersted
|
||||
// don't bother disconnect peers we haven't been interested
|
||||
// in (and that hasn't been interested in us) for a while
|
||||
// unless we have used up all our connection slots
|
||||
if (!m_interesting
|
||||
|
1098
src/piece_picker.cpp
1098
src/piece_picker.cpp
File diff suppressed because it is too large
Load Diff
@@ -187,7 +187,7 @@ namespace libtorrent
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_num_pieces(0)
|
||||
, m_sequenced_download_threshold(0)
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_ratio(0.f)
|
||||
, m_total_failed_bytes(0)
|
||||
@@ -249,7 +249,7 @@ namespace libtorrent
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_num_pieces(0)
|
||||
, m_sequenced_download_threshold(0)
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_ratio(0.f)
|
||||
, m_total_failed_bytes(0)
|
||||
@@ -1598,16 +1598,12 @@ namespace libtorrent
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we're a seed, we don't keep track of piece availability
|
||||
if (!is_seed())
|
||||
if (m_picker.get())
|
||||
{
|
||||
const std::vector<bool>& pieces = p->get_bitfield();
|
||||
|
||||
for (std::vector<bool>::const_iterator i = pieces.begin();
|
||||
i != pieces.end(); ++i)
|
||||
{
|
||||
if (*i) peer_lost(static_cast<int>(i - pieces.begin()));
|
||||
}
|
||||
TORRENT_ASSERT(std::count(pieces.begin(), pieces.end(), true)
|
||||
< int(pieces.size()));
|
||||
m_picker->dec_refcount(pieces);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2182,24 +2178,26 @@ namespace libtorrent
|
||||
|
||||
if (m_ses.m_connections.find(p) == m_ses.m_connections.end())
|
||||
{
|
||||
throw protocol_error("peer is not properly constructed");
|
||||
p->disconnect("peer is not properly constructed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ses.is_aborted())
|
||||
{
|
||||
throw protocol_error("session is closing");
|
||||
p->disconnect("session is closing");
|
||||
return;
|
||||
}
|
||||
|
||||
if (int(m_connections.size()) >= m_max_connections)
|
||||
{
|
||||
throw protocol_error("reached connection limit");
|
||||
p->disconnect("reached connection limit");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
// if new_connection throws, we have to remove the
|
||||
// it from the list.
|
||||
|
||||
#endif
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
@@ -2210,6 +2208,7 @@ namespace libtorrent
|
||||
#endif
|
||||
if (!m_policy.new_connection(*p))
|
||||
return;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@@ -2217,13 +2216,18 @@ namespace libtorrent
|
||||
(*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION "
|
||||
<< p->remote() << " policy::new_connection threw: " << e.what() << "\n";
|
||||
#endif
|
||||
throw;
|
||||
p->disconnect(e.what());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||
peer_iterator ci = m_connections.insert(p).first;
|
||||
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint());
|
||||
|
||||
#ifndef NDEBUG
|
||||
asio::error_code ec;
|
||||
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
|
||||
#endif
|
||||
|
||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
m_policy.check_invariant();
|
||||
#endif
|
||||
}
|
||||
@@ -2554,8 +2558,8 @@ namespace libtorrent
|
||||
// against its hashes.
|
||||
std::vector<int> verify_pieces;
|
||||
m_picker->files_checked(m_have_pieces, unfinished_pieces, verify_pieces);
|
||||
if (m_sequenced_download_threshold > 0)
|
||||
picker().set_sequenced_download_threshold(m_sequenced_download_threshold);
|
||||
if (m_sequential_download)
|
||||
picker().sequential_download(m_sequential_download);
|
||||
while (!verify_pieces.empty())
|
||||
{
|
||||
int piece = verify_pieces.back();
|
||||
@@ -2780,15 +2784,15 @@ namespace libtorrent
|
||||
}
|
||||
#endif
|
||||
|
||||
void torrent::set_sequenced_download_threshold(int threshold)
|
||||
void torrent::set_sequential_download(bool sd)
|
||||
{
|
||||
if (has_picker())
|
||||
{
|
||||
picker().set_sequenced_download_threshold(threshold);
|
||||
picker().sequential_download(sd);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sequenced_download_threshold = threshold;
|
||||
m_sequential_download = sd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3060,7 +3064,7 @@ namespace libtorrent
|
||||
|
||||
m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
|
||||
, shared_from_this(), _1, _2, f));
|
||||
#ifndef NDEBUG
|
||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
check_invariant();
|
||||
#endif
|
||||
}
|
||||
|
@@ -335,10 +335,10 @@ namespace libtorrent
|
||||
return torrent_status();
|
||||
}
|
||||
|
||||
void torrent_handle::set_sequenced_download_threshold(int threshold) const
|
||||
void torrent_handle::set_sequential_download(bool sd) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(set_sequenced_download_threshold(threshold));
|
||||
TORRENT_FORWARD(set_sequential_download(sd));
|
||||
}
|
||||
|
||||
std::string torrent_handle::name() const
|
||||
|
@@ -156,6 +156,17 @@ void print_pick(std::vector<piece_block> const& picked)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int test_pick(boost::shared_ptr<piece_picker> const& p)
|
||||
{
|
||||
std::vector<piece_block> picked;
|
||||
const std::vector<int> empty_vector;
|
||||
p->pick_pieces(string2vec("*******"), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
|
||||
print_pick(picked);
|
||||
TEST_CHECK(verify_pick(p, picked));
|
||||
TEST_CHECK(int(picked.size()) == 1);
|
||||
return picked[0].piece_index;
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
|
||||
@@ -236,7 +247,7 @@ int test_main()
|
||||
TEST_CHECK(picked.front().piece_index == 0);
|
||||
|
||||
// ========================================================
|
||||
|
||||
/*
|
||||
// test sequenced download
|
||||
p = setup_picker("7654321", " ", "", "");
|
||||
picked.clear();
|
||||
@@ -283,7 +294,7 @@ int test_main()
|
||||
TEST_CHECK(int(picked.size()) == 6 * blocks_per_piece);
|
||||
for (int i = 0; i < 6 * blocks_per_piece && i < int(picked.size()); ++i)
|
||||
TEST_CHECK(picked[i].piece_index == i / blocks_per_piece);
|
||||
|
||||
*/
|
||||
// ========================================================
|
||||
|
||||
// test piece priorities
|
||||
@@ -405,6 +416,27 @@ int test_main()
|
||||
|
||||
// ========================================================
|
||||
|
||||
// test inc_ref and dec_ref
|
||||
p = setup_picker("1233333", " * ", "", "");
|
||||
TEST_CHECK(test_pick(p) == 0);
|
||||
|
||||
p->dec_refcount(0);
|
||||
TEST_CHECK(test_pick(p) == 1);
|
||||
|
||||
p->dec_refcount(4);
|
||||
p->dec_refcount(4);
|
||||
TEST_CHECK(test_pick(p) == 4);
|
||||
|
||||
// decrease refcount on something that's not in the piece list
|
||||
p->dec_refcount(5);
|
||||
p->inc_refcount(5);
|
||||
|
||||
p->inc_refcount(0);
|
||||
p->dec_refcount(4);
|
||||
TEST_CHECK(test_pick(p) == 0);
|
||||
|
||||
// ========================================================
|
||||
/*
|
||||
// test have_all and have_none, with a sequenced download threshold
|
||||
p = setup_picker("1233333", "* ", "", "");
|
||||
p->set_sequenced_download_threshold(3);
|
||||
@@ -432,7 +464,7 @@ int test_main()
|
||||
TEST_CHECK(picked[1 * blocks_per_piece].piece_index == 4);
|
||||
TEST_CHECK(picked[2 * blocks_per_piece].piece_index == 5);
|
||||
TEST_CHECK(picked[3 * blocks_per_piece].piece_index == 6);
|
||||
|
||||
*/
|
||||
// ========================================================
|
||||
|
||||
// test unverified_blocks, marking blocks and get_downloader
|
||||
|
Reference in New Issue
Block a user