From 1a081561c439157d5c0fd51b3ce89dd3b7494c94 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 17 Jun 2006 01:29:36 +0000 Subject: [PATCH] fixed bug in tracker_connection (spotted by tianhao qui) and fixed a performance problem in the piece picker that takes over blocks from other peers (also spotted by tianhao qui) --- src/policy.cpp | 45 +++++++++++++++++++++++++++++++---------- src/tracker_manager.cpp | 2 +- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/policy.cpp b/src/policy.cpp index 06eccade9..728ecdaa0 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -150,11 +150,14 @@ namespace { peer_connection* peer = 0; + const int initial_queue_size = (int)c.download_queue().size() + + (int)c.request_queue().size(); + // This peer's weight will be the minimum, to prevent // cancelling requests from a faster peer. - float min_weight = (int)c.download_queue().size() == 0 + float min_weight = initial_queue_size == 0 ? std::numeric_limits::max() - : c.statistics().download_payload_rate() / (int)c.download_queue().size(); + : c.statistics().download_payload_rate() / initial_queue_size; // find the peer with the lowest download // speed that also has a piece that this @@ -170,18 +173,29 @@ namespace if (std::find(ignore.begin(), ignore.end(), i->second) != ignore.end()) continue; - const std::deque& queue = i->second->download_queue(); - const int queue_size = (int)i->second->download_queue().size(); + const std::deque& download_queue = i->second->download_queue(); + const std::deque& request_queue = i->second->request_queue(); + const int queue_size = (int)i->second->download_queue().size() + + (int)i->second->request_queue().size(); const float weight = queue_size == 0 ? std::numeric_limits::max() : i->second->statistics().download_payload_rate() / queue_size; + // if the peer's (i) weight is less than the lowest we've found so + // far (weight == priority) and it has blocks in its request- + // or download queue that we could request from this peer (c), + // replace the currently lowest ranking peer. if (weight < min_weight - && std::find_first_of( + && (std::find_first_of( busy_pieces.begin() , busy_pieces.end() - , queue.begin() - , queue.end()) != busy_pieces.end()) + , request_queue.begin() + , request_queue.end()) != busy_pieces.end() + || std::find_first_of( + busy_pieces.begin() + , busy_pieces.end() + , download_queue.begin() + , download_queue.end()) != busy_pieces.end())) { peer = i->second; min_weight = weight; @@ -199,31 +213,40 @@ namespace std::deque::const_reverse_iterator common_block = std::find_first_of( + peer->request_queue().rbegin() + , peer->request_queue().rend() + , busy_pieces.begin() + , busy_pieces.end()); + + if (common_block == peer->request_queue().rend()) + { + common_block = std::find_first_of( peer->download_queue().rbegin() , peer->download_queue().rend() , busy_pieces.begin() , busy_pieces.end()); + assert(common_block != peer->download_queue().rend()); + } - assert(common_block != peer->download_queue().rend()); piece_block block = *common_block; peer->cancel_request(block); c.add_request(block); - // the one we interrupted may need to request a new piece + // the one we interrupted may need to request a new piece. // make sure it doesn't take over a block from the peer // that just took over its block ignore.push_back(&c); request_a_block(t, *peer, ignore); num_requests--; - // this peer doesn't have a faster connection than the - // slowest peer. Don't take over any blocks const int queue_size = (int)c.download_queue().size() + (int)c.request_queue().size(); const float weight = queue_size == 0 ? std::numeric_limits::max() : c.statistics().download_payload_rate() / queue_size; + // this peer doesn't have a faster connection than the + // slowest peer. Don't take over any blocks if (weight <= min_weight) break; } c.send_block_requests(); diff --git a/src/tracker_manager.cpp b/src/tracker_manager.cpp index 34db162af..4c1a51ead 100755 --- a/src/tracker_manager.cpp +++ b/src/tracker_manager.cpp @@ -408,8 +408,8 @@ namespace libtorrent void tracker_connection::close() { - m_man.remove_request(this); cancel(); + m_man.remove_request(this); } void tracker_manager::remove_request(tracker_connection const* c)