*** empty log message ***
This commit is contained in:
parent
157621d81c
commit
13b2590c0b
|
@ -378,7 +378,7 @@ int main(int argc, char* argv[])
|
||||||
out << "next announce: " << boost::posix_time::to_simple_string(t) << "\n";
|
out << "next announce: " << boost::posix_time::to_simple_string(t) << "\n";
|
||||||
out << "tracker: " << s.current_tracker << "\n";
|
out << "tracker: " << s.current_tracker << "\n";
|
||||||
|
|
||||||
out << "___________________________________\n";
|
// out << "___________________________________\n";
|
||||||
|
|
||||||
for (std::vector<peer_info>::iterator i = peers.begin();
|
for (std::vector<peer_info>::iterator i = peers.begin();
|
||||||
i != peers.end();
|
i != peers.end();
|
||||||
|
@ -389,17 +389,17 @@ int main(int argc, char* argv[])
|
||||||
<< "u:" << add_suffix(i->up_speed) << "/s "
|
<< "u:" << add_suffix(i->up_speed) << "/s "
|
||||||
<< "(" << add_suffix(i->total_upload) << ") "
|
<< "(" << add_suffix(i->total_upload) << ") "
|
||||||
<< "ul:" << add_suffix(i->upload_limit) << "/s "
|
<< "ul:" << add_suffix(i->upload_limit) << "/s "
|
||||||
// << "uc:" << add_suffix(i->upload_ceiling) << "/s "
|
<< "uc:" << add_suffix(i->upload_ceiling) << "/s "
|
||||||
// << "df:" << ratio(i->total_download, i->total_upload) << " "
|
// << "df:" << ratio(i->total_download, i->total_upload) << " "
|
||||||
<< "q:" << i->download_queue_length << " "
|
// << "q:" << i->download_queue_length << " "
|
||||||
<< "r:" << i->upload_queue_length << " "
|
// << "r:" << i->upload_queue_length << " "
|
||||||
<< "f:"
|
// << "f:"
|
||||||
<< static_cast<const char*>((i->flags & peer_info::interesting)?"I":"_")
|
// << static_cast<const char*>((i->flags & peer_info::interesting)?"I":"_")
|
||||||
<< static_cast<const char*>((i->flags & peer_info::choked)?"C":"_")
|
// << static_cast<const char*>((i->flags & peer_info::choked)?"C":"_")
|
||||||
<< static_cast<const char*>((i->flags & peer_info::remote_interested)?"i":"_")
|
// << static_cast<const char*>((i->flags & peer_info::remote_interested)?"i":"_")
|
||||||
<< static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_")
|
// << static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_")
|
||||||
<< static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_")
|
// << static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_")
|
||||||
<< static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r")
|
// << static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r")
|
||||||
<< "\n";
|
<< "\n";
|
||||||
/*
|
/*
|
||||||
if (i->downloading_piece_index >= 0)
|
if (i->downloading_piece_index >= 0)
|
||||||
|
@ -415,7 +415,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
out << "___________________________________\n";
|
out << "___________________________________\n";
|
||||||
|
|
||||||
i->get_download_queue(queue);
|
i->get_download_queue(queue);
|
||||||
|
@ -436,7 +436,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "___________________________________\n";
|
out << "___________________________________\n";
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::deque<std::string>::iterator i = events.begin();
|
for (std::deque<std::string>::iterator i = events.begin();
|
||||||
|
|
|
@ -55,6 +55,9 @@ namespace libtorrent
|
||||||
// It takes into account the current use, and the consumer's desired use.
|
// It takes into account the current use, and the consumer's desired use.
|
||||||
// Should be invoked periodically to allow it adjust to the situation (make
|
// Should be invoked periodically to allow it adjust to the situation (make
|
||||||
// sure "used" is updated between calls!).
|
// sure "used" is updated between calls!).
|
||||||
|
// If resources = std::numeric_limits<int>::max() it means there is an infinite
|
||||||
|
// supply of resources (so everyone can get what they want).
|
||||||
|
|
||||||
|
|
||||||
void allocate_resources(int resources,
|
void allocate_resources(int resources,
|
||||||
std::vector<resource_request *> & requests);
|
std::vector<resource_request *> & requests);
|
||||||
|
|
|
@ -212,12 +212,12 @@ namespace libtorrent
|
||||||
// left until will stop sending.
|
// left until will stop sending.
|
||||||
// if the send_quota is -1, it means the
|
// if the send_quota is -1, it means the
|
||||||
// quota is unlimited.
|
// quota is unlimited.
|
||||||
int send_quota_left() const { return m_send_quota_left; }
|
int send_quota_left() const { return upload_bandwidth.given-upload_bandwidth.used; }
|
||||||
|
|
||||||
void update_send_quota_left()
|
void update_send_quota_left()
|
||||||
{
|
{
|
||||||
m_send_quota_left = upload_bandwidth.given;
|
upload_bandwidth.used=0;
|
||||||
if (m_send_quota_left > 0) send_buffer_updated();
|
send_buffer_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type total_free_upload() const
|
size_type total_free_upload() const
|
||||||
|
@ -465,19 +465,6 @@ namespace libtorrent
|
||||||
// that we give the free upload, to keep the balance.
|
// that we give the free upload, to keep the balance.
|
||||||
size_type m_free_upload;
|
size_type m_free_upload;
|
||||||
|
|
||||||
// this is used to limit upload bandwidth.
|
|
||||||
// it is reset to the allowed number of
|
|
||||||
// bytes to send frequently. Every time
|
|
||||||
// thie peer send some data,
|
|
||||||
// m_send_quota_left variable will be decreased
|
|
||||||
// so it can limit the number of bytes next
|
|
||||||
// time it sends data. when it reaches zero
|
|
||||||
// the client will stop send data and await
|
|
||||||
// more quota. if it is set to -1, the peer
|
|
||||||
// will ignore the qouta and send at maximum
|
|
||||||
// speed
|
|
||||||
int m_send_quota_left;
|
|
||||||
|
|
||||||
// for every valid piece we receive where this
|
// for every valid piece we receive where this
|
||||||
// peer was one of the participants, we increase
|
// peer was one of the participants, we increase
|
||||||
// this value. For every invalid piece we receive
|
// this value. For every invalid piece we receive
|
||||||
|
@ -536,7 +523,7 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_send_quota_left > 0 || m_send_quota_left == -1);
|
assert(upload_bandwidth.used < upload_bandwidth.given);
|
||||||
assert(has_data());
|
assert(has_data());
|
||||||
if (!m_added_to_selector)
|
if (!m_added_to_selector)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
#include "libtorrent/allocate_resources.hpp"
|
||||||
|
#include "libtorrent/size_type.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/limits.hpp>
|
#include <boost/limits.hpp>
|
||||||
|
@ -51,7 +52,7 @@ namespace libtorrent
|
||||||
assert(sum>=a && sum>=b);
|
assert(sum>=a && sum>=b);
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
int round_up_division(int numer, int denom)
|
int round_up_division(int numer, int denom)
|
||||||
{
|
{
|
||||||
assert(numer>0);
|
assert(numer>0);
|
||||||
|
@ -66,13 +67,13 @@ namespace libtorrent
|
||||||
// for use with std::sort
|
// for use with std::sort
|
||||||
bool by_used(const resource_request *a, const resource_request *b)
|
bool by_used(const resource_request *a, const resource_request *b)
|
||||||
{ return a->used < b->used; }
|
{ return a->used < b->used; }
|
||||||
|
*/
|
||||||
// give num_resources to r,
|
// give num_resources to r,
|
||||||
// return how how many were actually accepted.
|
// return how how many were actually accepted.
|
||||||
int give(resource_request *r, int num_resources)
|
int give(resource_request *r, int num_resources)
|
||||||
{
|
{
|
||||||
assert(r);
|
assert(r);
|
||||||
assert(num_resources > 0);
|
assert(num_resources >= 0);
|
||||||
assert(r->given <= r->wanted);
|
assert(r->given <= r->wanted);
|
||||||
|
|
||||||
int accepted = std::min(num_resources, r->wanted - r->given);
|
int accepted = std::min(num_resources, r->wanted - r->given);
|
||||||
|
@ -84,6 +85,7 @@ namespace libtorrent
|
||||||
return accepted;
|
return accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sum of requests' "wanted" field.
|
||||||
int total_wanted(std::vector<resource_request *> & requests)
|
int total_wanted(std::vector<resource_request *> & requests)
|
||||||
{
|
{
|
||||||
int total_wanted=0;
|
int total_wanted=0;
|
||||||
|
@ -182,26 +184,93 @@ namespace libtorrent
|
||||||
|
|
||||||
assert(resources_to_distribute > 0);
|
assert(resources_to_distribute > 0);
|
||||||
|
|
||||||
std::random_shuffle(requests.begin(), requests.end());
|
|
||||||
std::sort(requests.begin(), requests.end(), by_used);
|
|
||||||
|
|
||||||
while(resources_to_distribute > 0)
|
while(resources_to_distribute > 0)
|
||||||
{
|
{
|
||||||
for(int i = 0;
|
#if 1
|
||||||
i < (int)requests.size() && resources_to_distribute > 0;
|
int num_active=0;
|
||||||
++i)
|
for(int i = 0;i < (int)requests.size();++i)
|
||||||
{
|
{
|
||||||
resources_to_distribute -=
|
resource_request *r=requests[i];
|
||||||
give(
|
if(r->given == r->wanted)
|
||||||
requests[i],
|
continue;
|
||||||
std::min(
|
num_active++;
|
||||||
requests[i]->used+1,
|
|
||||||
round_up_division(
|
|
||||||
(int)resources_to_distribute,
|
|
||||||
(int)requests.size()-i)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int max_give=resources_to_distribute/num_active;
|
||||||
|
max_give=std::max(max_give,1);
|
||||||
|
|
||||||
|
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
|
||||||
|
{
|
||||||
|
resource_request *r=requests[i];
|
||||||
|
if(r->given == r->wanted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int toGive = 1+std::min(max_give-1,r->used);
|
||||||
|
resources_to_distribute-=give(r,toGive);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_type total_used=0;
|
||||||
|
size_type max_used=0;
|
||||||
|
for(int i = 0;i < (int)requests.size();++i)
|
||||||
|
{
|
||||||
|
resource_request *r=requests[i];
|
||||||
|
if(r->given == r->wanted)
|
||||||
|
continue;
|
||||||
|
assert(r->given < r->wanted);
|
||||||
|
|
||||||
|
max_used = std::max(max_used, (size_type)r->used + 1);
|
||||||
|
total_used += (size_type)r->used + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type kNumer=resources_to_distribute;
|
||||||
|
size_type kDenom=total_used;
|
||||||
|
|
||||||
|
{
|
||||||
|
size_type numer=1;
|
||||||
|
size_type denom=max_used;
|
||||||
|
|
||||||
|
if(numer*kDenom >= kNumer*denom)
|
||||||
|
{
|
||||||
|
kNumer=numer;
|
||||||
|
kDenom=denom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0;i < (int)requests.size();++i)
|
||||||
|
{
|
||||||
|
resource_request *r=requests[i];
|
||||||
|
if(r->given == r->wanted)
|
||||||
|
continue;
|
||||||
|
assert(r->given < r->wanted);
|
||||||
|
|
||||||
|
size_type numer = r->wanted - r->given;
|
||||||
|
size_type denom = (size_type)r->used + 1;
|
||||||
|
|
||||||
|
if(numer*kDenom <= kNumer*denom)
|
||||||
|
{
|
||||||
|
kNumer=numer;
|
||||||
|
kDenom=denom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
|
||||||
|
{
|
||||||
|
resource_request *r=requests[i];
|
||||||
|
if(r->given == r->wanted)
|
||||||
|
continue;
|
||||||
|
assert(r->given < r->wanted);
|
||||||
|
|
||||||
|
size_type used = (size_type)r->used + 1;
|
||||||
|
size_type toGive = (used * kNumer) / kDenom;
|
||||||
|
if(toGive>std::numeric_limits<int>::max())
|
||||||
|
toGive=std::numeric_limits<int>::max();
|
||||||
|
resources_to_distribute-=give(r,(int)toGive);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
assert(resources_to_distribute >= 0);
|
||||||
}
|
}
|
||||||
assert(resources_to_distribute == 0);
|
assert(resources_to_distribute == 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -100,7 +100,6 @@ namespace libtorrent
|
||||||
, m_supports_extensions(false)
|
, m_supports_extensions(false)
|
||||||
, m_num_pieces(0)
|
, m_num_pieces(0)
|
||||||
, m_free_upload(0)
|
, m_free_upload(0)
|
||||||
, m_send_quota_left(0)
|
|
||||||
, m_trust_points(0)
|
, m_trust_points(0)
|
||||||
, m_num_invalid_requests(0)
|
, m_num_invalid_requests(0)
|
||||||
, m_last_piece(boost::posix_time::second_clock::local_time())
|
, m_last_piece(boost::posix_time::second_clock::local_time())
|
||||||
|
@ -162,7 +161,6 @@ namespace libtorrent
|
||||||
, m_supports_extensions(false)
|
, m_supports_extensions(false)
|
||||||
, m_num_pieces(0)
|
, m_num_pieces(0)
|
||||||
, m_free_upload(0)
|
, m_free_upload(0)
|
||||||
, m_send_quota_left(0)
|
|
||||||
, m_trust_points(0)
|
, m_trust_points(0)
|
||||||
, m_num_invalid_requests(0)
|
, m_num_invalid_requests(0)
|
||||||
, m_last_piece(boost::posix_time::second_clock::local_time())
|
, m_last_piece(boost::posix_time::second_clock::local_time())
|
||||||
|
@ -1226,7 +1224,7 @@ namespace libtorrent
|
||||||
|
|
||||||
m_statistics.second_tick();
|
m_statistics.second_tick();
|
||||||
|
|
||||||
update_send_quota_left();
|
// update_send_quota_left();
|
||||||
|
|
||||||
// If the client sends more data
|
// If the client sends more data
|
||||||
// we send it data faster, otherwise, slower.
|
// we send it data faster, otherwise, slower.
|
||||||
|
@ -1240,7 +1238,10 @@ namespace libtorrent
|
||||||
// if we have downloaded more than one piece more
|
// if we have downloaded more than one piece more
|
||||||
// than we have uploaded OR if we are a seed
|
// than we have uploaded OR if we are a seed
|
||||||
// have an unlimited upload rate
|
// have an unlimited upload rate
|
||||||
|
// if(!m_send_buffer.empty() || (!m_requests.empty() && !is_choked()))
|
||||||
upload_bandwidth.wanted = std::numeric_limits<int>::max();
|
upload_bandwidth.wanted = std::numeric_limits<int>::max();
|
||||||
|
// else
|
||||||
|
// upload_bandwidth.wanted = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1566,7 +1567,7 @@ namespace libtorrent
|
||||||
// we want to send data
|
// we want to send data
|
||||||
return ((!m_requests.empty() && !m_choked)
|
return ((!m_requests.empty() && !m_choked)
|
||||||
|| !m_send_buffer.empty())
|
|| !m_send_buffer.empty())
|
||||||
&& m_send_quota_left != 0;
|
&& upload_bandwidth.used < upload_bandwidth.given;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
@ -1645,17 +1646,15 @@ namespace libtorrent
|
||||||
m_announce_queue.clear();
|
m_announce_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_send_quota_left != 0);
|
assert(upload_bandwidth.used < upload_bandwidth.given);
|
||||||
|
|
||||||
// send the actual buffer
|
// send the actual buffer
|
||||||
if (!m_send_buffer.empty())
|
if (!m_send_buffer.empty())
|
||||||
{
|
{
|
||||||
|
|
||||||
int amount_to_send = (int)m_send_buffer.size();
|
int amount_to_send = (int)m_send_buffer.size();
|
||||||
assert(m_send_quota_left != 0);
|
assert(upload_bandwidth.used < upload_bandwidth.given);
|
||||||
if (m_send_quota_left > 0)
|
amount_to_send = std::min(upload_bandwidth.given-upload_bandwidth.used, amount_to_send);
|
||||||
amount_to_send = std::min(m_send_quota_left, amount_to_send);
|
|
||||||
|
|
||||||
|
|
||||||
// we have data that's scheduled for sending
|
// we have data that's scheduled for sending
|
||||||
int sent = m_socket->send(
|
int sent = m_socket->send(
|
||||||
|
@ -1664,11 +1663,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (sent > 0)
|
if (sent > 0)
|
||||||
{
|
{
|
||||||
if (m_send_quota_left != -1)
|
upload_bandwidth.used += sent;
|
||||||
{
|
|
||||||
assert(m_send_quota_left >= sent);
|
|
||||||
m_send_quota_left -= sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// manage the payload markers
|
// manage the payload markers
|
||||||
int amount_payload = 0;
|
int amount_payload = 0;
|
||||||
|
|
275
src/session.cpp
275
src/session.cpp
|
@ -91,6 +91,12 @@ namespace
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adjusts the upload rates of every peer connection
|
||||||
|
// to make sure the sum of all send quotas equals
|
||||||
|
// the given upload_limit. An upload limit of
|
||||||
|
// std::numeric_limits<int>::max() means unlimited upload
|
||||||
|
// rate, but the rates of each peer has to be set anyway,
|
||||||
|
// since it depends on the download rate from the peer.
|
||||||
void control_upload_rates(
|
void control_upload_rates(
|
||||||
int upload_limit,
|
int upload_limit,
|
||||||
libtorrent::detail::session_impl::connection_map connections)
|
libtorrent::detail::session_impl::connection_map connections)
|
||||||
|
@ -98,56 +104,29 @@ namespace
|
||||||
assert(upload_limit >= 0);
|
assert(upload_limit >= 0);
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
std::vector<resource_consumer> peers;
|
std::vector<resource_request *> requests;
|
||||||
|
|
||||||
for (detail::session_impl::connection_map::iterator c = connections.begin();
|
for (detail::session_impl::connection_map::iterator c = connections.begin();
|
||||||
c != connections.end(); ++c)
|
c != connections.end(); ++c)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<peer_connection> p = c->second;
|
boost::shared_ptr<peer_connection> p = c->second;
|
||||||
int estimated_upload_capacity=
|
p->upload_bandwidth.used = (int) ((p->statistics().upload_rate()+p->upload_bandwidth.used) / 2);
|
||||||
p->has_data() ? (int)ceil(p->statistics().upload_rate()) // std::max(10,(int)ceil(p->statistics().upload_rate()*1.1f))
|
// p->has_data() ? (int) (p->upload_bandwidth.given - p->send_quota_left()) //ceil(p->statistics().upload_rate())
|
||||||
: 1;
|
// : 0;
|
||||||
|
|
||||||
int limit=p->send_quota_limit();
|
requests.push_back(&p->upload_bandwidth);
|
||||||
if(limit==-1)
|
|
||||||
limit=std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
peers.push_back(resource_consumer(p,limit,estimated_upload_capacity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allocate_resources(upload_limit, peers);
|
allocate_resources(upload_limit, requests);
|
||||||
|
|
||||||
for (std::vector<resource_consumer>::iterator r=peers.begin();
|
for (detail::session_impl::connection_map::iterator c = connections.begin();
|
||||||
r!=peers.end(); ++r)
|
c != connections.end(); ++c)
|
||||||
{
|
{
|
||||||
boost::any_cast<boost::shared_ptr<peer_connection> >
|
boost::shared_ptr<peer_connection> p = c->second;
|
||||||
(r->who())->set_send_quota(r->allowed_use());
|
p->update_send_quota_left();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
{
|
|
||||||
int sum_quota = 0;
|
|
||||||
int sum_quota_limit = 0;
|
|
||||||
for (detail::session_impl::connection_map::iterator i = connections.begin();
|
|
||||||
i != connections.end();
|
|
||||||
++i)
|
|
||||||
{
|
|
||||||
peer_connection& p = *i->second;
|
|
||||||
|
|
||||||
int quota=p.send_quota();
|
|
||||||
int quota_limit=p.send_quota_limit();
|
|
||||||
if(quota==-1)
|
|
||||||
quota=std::numeric_limits<int>::max();
|
|
||||||
if(quota_limit==-1)
|
|
||||||
quota_limit=std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
sum_quota = saturated_add(sum_quota,quota);
|
|
||||||
sum_quota_limit = saturated_add(sum_quota_limit,quota_limit);
|
|
||||||
}
|
|
||||||
assert(sum_quota == std::min(upload_limit,sum_quota_limit));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void control_number_of_connections(
|
void control_number_of_connections(
|
||||||
int connections_limit,
|
int connections_limit,
|
||||||
libtorrent::detail::session_impl::torrent_map hash_list)
|
libtorrent::detail::session_impl::torrent_map hash_list)
|
||||||
|
@ -180,197 +159,6 @@ namespace
|
||||||
// (r->who())->set_send_quota(r->allowed_use());
|
// (r->who())->set_send_quota(r->allowed_use());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// This struct is used by control_upload_rates() below. It keeps
|
|
||||||
// track how much bandwidth has been allocated to each connection
|
|
||||||
// and other relevant information to assist in the allocation process.
|
|
||||||
struct connection_info
|
|
||||||
{
|
|
||||||
libtorrent::peer_connection* p; // which peer_connection this info refers to
|
|
||||||
int allocated_quota; // bandwidth allocated to this peer connection
|
|
||||||
int quota_limit; // bandwidth limit
|
|
||||||
int estimated_upload_capacity; // estimated channel bandwidth
|
|
||||||
|
|
||||||
bool operator < (const connection_info &other) const
|
|
||||||
{
|
|
||||||
return estimated_upload_capacity < other.estimated_upload_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
int give(int amount)
|
|
||||||
{
|
|
||||||
|
|
||||||
// if amount > 0, try to add amount to the allocated quota.
|
|
||||||
// if amount < 0, try to subtract abs(amount) from the allocated quota
|
|
||||||
//
|
|
||||||
// Quota will not go above quota_limit or below 0. This means that
|
|
||||||
// not all the amount given or taken may be accepted.
|
|
||||||
//
|
|
||||||
// return value: how much quota was actually added (or subtracted if negative).
|
|
||||||
|
|
||||||
int old_quota=allocated_quota;
|
|
||||||
allocated_quota+=amount;
|
|
||||||
if(quota_limit!=-1)
|
|
||||||
allocated_quota=std::min(allocated_quota,quota_limit);
|
|
||||||
allocated_quota=std::max(0,allocated_quota);
|
|
||||||
return allocated_quota-old_quota;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// adjusts the upload rates of every peer connection
|
|
||||||
// to make sure the sum of all send quotas equals
|
|
||||||
// the given upload_limit. An upload limit of -1 means
|
|
||||||
// unlimited upload rate, but the rates of each peer
|
|
||||||
// has to be set anyway, since it depends on the download
|
|
||||||
// rate from the peer.
|
|
||||||
void control_upload_rates(
|
|
||||||
int upload_limit
|
|
||||||
, libtorrent::detail::session_impl::connection_map connections)
|
|
||||||
{
|
|
||||||
using namespace libtorrent;
|
|
||||||
|
|
||||||
assert(upload_limit > 0 || upload_limit == -1);
|
|
||||||
|
|
||||||
if (connections.empty()) return;
|
|
||||||
|
|
||||||
|
|
||||||
if (upload_limit == -1)
|
|
||||||
{
|
|
||||||
for (detail::session_impl::connection_map::iterator i = connections.begin();
|
|
||||||
i != connections.end();
|
|
||||||
++i)
|
|
||||||
{
|
|
||||||
// there's no limit, set the quota to max
|
|
||||||
// allowed
|
|
||||||
peer_connection& p = *i->second;
|
|
||||||
p.set_send_quota(p.send_quota_limit());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// There's an upload limit, so we need to distribute the available
|
|
||||||
// upload bandwidth among the peer_connections fairly, but not
|
|
||||||
// wastefully.
|
|
||||||
|
|
||||||
// For each peer_connection, keep some local data about their
|
|
||||||
// quota limit and estimated upload capacity, and how much quota
|
|
||||||
// has been allocated to them.
|
|
||||||
|
|
||||||
std::vector<connection_info> peer_info;
|
|
||||||
|
|
||||||
for (detail::session_impl::connection_map::iterator i = connections.begin();
|
|
||||||
i != connections.end();
|
|
||||||
++i)
|
|
||||||
{
|
|
||||||
peer_connection& p = *i->second;
|
|
||||||
connection_info pi;
|
|
||||||
|
|
||||||
pi.p = &p;
|
|
||||||
pi.allocated_quota = 0; // we haven't given it any bandwith yet
|
|
||||||
pi.quota_limit = p.send_quota_limit();
|
|
||||||
|
|
||||||
pi.estimated_upload_capacity=
|
|
||||||
p.has_data() ? std::max(10,(int)ceil(p.statistics().upload_rate()*1.1f))
|
|
||||||
// If there's no data to send, upload capacity is practically 0.
|
|
||||||
// Here we set it to 1 though, because otherwise it will not be able
|
|
||||||
// to accept any quota at all, which may upset quota_limit balances.
|
|
||||||
: 1;
|
|
||||||
|
|
||||||
peer_info.push_back(pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum all peer_connections' quota limit to get the total quota limit.
|
|
||||||
|
|
||||||
int sum_total_of_quota_limits=0;
|
|
||||||
for (int i = 0; i < (int)peer_info.size(); ++i)
|
|
||||||
{
|
|
||||||
int quota_limit = peer_info[i].quota_limit;
|
|
||||||
if (quota_limit == -1)
|
|
||||||
{
|
|
||||||
// quota_limit=-1 means infinite, so
|
|
||||||
// sum_total_of_quota_limits will be infinite too...
|
|
||||||
sum_total_of_quota_limits = std::numeric_limits<int>::max();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sum_total_of_quota_limits += quota_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is how much total bandwidth that can be distributed.
|
|
||||||
int quota_left_to_distribute = std::min(upload_limit,sum_total_of_quota_limits);
|
|
||||||
|
|
||||||
|
|
||||||
// Sort w.r.t. channel capacitiy, lowest channel capacity first.
|
|
||||||
// Makes it easy to traverse the list in sorted order.
|
|
||||||
std::sort(peer_info.begin(),peer_info.end());
|
|
||||||
|
|
||||||
|
|
||||||
// Distribute quota until there's nothing more to distribute
|
|
||||||
|
|
||||||
while (quota_left_to_distribute != 0)
|
|
||||||
{
|
|
||||||
assert(quota_left_to_distribute > 0);
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)peer_info.size(); ++i)
|
|
||||||
{
|
|
||||||
// Traverse the peer list from slowest connection to fastest.
|
|
||||||
|
|
||||||
// In each step, share bandwidth equally between this peer_connection
|
|
||||||
// and the following faster peer_connections.
|
|
||||||
//
|
|
||||||
// Rounds upwards to avoid trying to give 0 bandwidth to someone
|
|
||||||
// (may get caught in an endless loop otherwise)
|
|
||||||
|
|
||||||
int num_peers_left_to_share_quota = (int)peer_info.size() - i;
|
|
||||||
int try_to_give_to_this_peer
|
|
||||||
= (quota_left_to_distribute + num_peers_left_to_share_quota - 1)
|
|
||||||
/ num_peers_left_to_share_quota;
|
|
||||||
|
|
||||||
// But do not allocate more than the estimated upload capacity.
|
|
||||||
try_to_give_to_this_peer = std::min(
|
|
||||||
peer_info[i].estimated_upload_capacity
|
|
||||||
, try_to_give_to_this_peer);
|
|
||||||
|
|
||||||
// Also, when the peer is given quota, it will
|
|
||||||
// not accept more than it's quota_limit.
|
|
||||||
int quota_actually_given_to_peer
|
|
||||||
= peer_info[i].give(try_to_give_to_this_peer);
|
|
||||||
|
|
||||||
quota_left_to_distribute -= quota_actually_given_to_peer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, inform the peers of how much quota they get.
|
|
||||||
|
|
||||||
for(int i = 0; i < (int)peer_info.size(); ++i)
|
|
||||||
peer_info[i].p->set_send_quota(peer_info[i].allocated_quota);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
{
|
|
||||||
int sum_quota = 0;
|
|
||||||
int sum_quota_limit = 0;
|
|
||||||
for (detail::session_impl::connection_map::iterator i = connections.begin();
|
|
||||||
i != connections.end();
|
|
||||||
++i)
|
|
||||||
{
|
|
||||||
peer_connection& p = *i->second;
|
|
||||||
sum_quota += p.send_quota();
|
|
||||||
|
|
||||||
if(p.send_quota_limit() == -1)
|
|
||||||
{
|
|
||||||
sum_quota_limit=std::numeric_limits<int>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sum_quota_limit!=std::numeric_limits<int>::max())
|
|
||||||
{
|
|
||||||
sum_quota_limit += p.send_quota_limit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(sum_quota == std::min(upload_limit,sum_quota_limit));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,8 +378,7 @@ namespace libtorrent
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
i->second->abort();
|
i->second->abort();
|
||||||
m_tracker_manager.queue_request(
|
m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_port));
|
||||||
i->second->generate_tracker_request(m_listen_port));
|
|
||||||
}
|
}
|
||||||
m_connections.clear();
|
m_connections.clear();
|
||||||
m_torrents.clear();
|
m_torrents.clear();
|
||||||
|
@ -680,9 +467,9 @@ namespace libtorrent
|
||||||
if (*i == listener)
|
if (*i == listener)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<libtorrent::socket> s = (*i)->accept();
|
boost::shared_ptr<libtorrent::socket> s = (*i)->accept();
|
||||||
s->set_blocking(false);
|
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
|
s->set_blocking(false);
|
||||||
// we got a connection request!
|
// we got a connection request!
|
||||||
m_incoming_connection = true;
|
m_incoming_connection = true;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -693,7 +480,12 @@ namespace libtorrent
|
||||||
boost::shared_ptr<peer_connection> c(
|
boost::shared_ptr<peer_connection> c(
|
||||||
new peer_connection(*this, m_selector, s));
|
new peer_connection(*this, m_selector, s));
|
||||||
|
|
||||||
if (m_upload_rate != -1) c->set_send_quota(0);
|
if (m_upload_rate != -1)
|
||||||
|
{
|
||||||
|
c->upload_bandwidth.given = 0;
|
||||||
|
c->update_send_quota_left();
|
||||||
|
}
|
||||||
|
|
||||||
m_connections.insert(std::make_pair(s, c));
|
m_connections.insert(std::make_pair(s, c));
|
||||||
m_selector.monitor_readability(s);
|
m_selector.monitor_readability(s);
|
||||||
m_selector.monitor_errors(s);
|
m_selector.monitor_errors(s);
|
||||||
|
@ -824,7 +616,6 @@ namespace libtorrent
|
||||||
|
|
||||||
// check each torrent for abortion or
|
// check each torrent for abortion or
|
||||||
// tracker updates
|
// tracker updates
|
||||||
assert(m_disconnect_peer.empty());
|
|
||||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
||||||
= m_torrents.begin();
|
= m_torrents.begin();
|
||||||
i != m_torrents.end();)
|
i != m_torrents.end();)
|
||||||
|
@ -834,9 +625,6 @@ namespace libtorrent
|
||||||
m_tracker_manager.queue_request(
|
m_tracker_manager.queue_request(
|
||||||
i->second->generate_tracker_request(m_listen_port));
|
i->second->generate_tracker_request(m_listen_port));
|
||||||
i->second->disconnect_all();
|
i->second->disconnect_all();
|
||||||
// make sure all connection are closed
|
|
||||||
// before the torrent is removed
|
|
||||||
purge_connections();
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
sha1_hash i_hash = i->second->torrent_file().info_hash();
|
sha1_hash i_hash = i->second->torrent_file().info_hash();
|
||||||
#endif
|
#endif
|
||||||
|
@ -850,8 +638,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_tracker_manager.queue_request(
|
m_tracker_manager.queue_request(
|
||||||
i->second->generate_tracker_request(m_listen_port)
|
i->second->generate_tracker_request(m_listen_port)
|
||||||
, boost::get_pointer(i->second)
|
, boost::get_pointer(i->second));
|
||||||
, i->second->tracker_password());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i->second->second_tick();
|
i->second->second_tick();
|
||||||
|
@ -861,10 +648,11 @@ namespace libtorrent
|
||||||
|
|
||||||
// distribute the maximum upload rate among the peers
|
// distribute the maximum upload rate among the peers
|
||||||
|
|
||||||
control_upload_rates(m_upload_rate == -1
|
control_upload_rates(
|
||||||
|
m_upload_rate == -1
|
||||||
? std::numeric_limits<int>::max()
|
? std::numeric_limits<int>::max()
|
||||||
: m_upload_rate
|
: m_upload_rate
|
||||||
,m_connections);
|
, m_connections);
|
||||||
|
|
||||||
|
|
||||||
m_tracker_manager.tick();
|
m_tracker_manager.tick();
|
||||||
|
@ -937,7 +725,7 @@ namespace libtorrent
|
||||||
"peer_connection::has_data() != is_writability_monitored()\n";
|
"peer_connection::has_data() != is_writability_monitored()\n";
|
||||||
error_log << "peer_connection::has_data() " << p->has_data() << "\n";
|
error_log << "peer_connection::has_data() " << p->has_data() << "\n";
|
||||||
error_log << "peer_connection::send_quota_left " << p->send_quota_left() << "\n";
|
error_log << "peer_connection::send_quota_left " << p->send_quota_left() << "\n";
|
||||||
error_log << "peer_connection::send_quota " << p->send_quota() << "\n";
|
error_log << "peer_connection::upload_bandwidth.given " << p->upload_bandwidth.given << "\n";
|
||||||
error_log << "peer_connection::get_peer_id " << p->get_peer_id() << "\n";
|
error_log << "peer_connection::get_peer_id " << p->get_peer_id() << "\n";
|
||||||
error_log << "place: " << place << "\n";
|
error_log << "place: " << place << "\n";
|
||||||
error_log.flush();
|
error_log.flush();
|
||||||
|
@ -1105,7 +893,8 @@ namespace libtorrent
|
||||||
= m_impl.m_connections.begin();
|
= m_impl.m_connections.begin();
|
||||||
i != m_impl.m_connections.end();)
|
i != m_impl.m_connections.end();)
|
||||||
{
|
{
|
||||||
i->second->set_send_quota(-1);
|
i->second->upload_bandwidth.given = std::numeric_limits<int>::max();
|
||||||
|
i->second->update_send_quota_left();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,22 +192,14 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock l(m_ses->m_mutex);
|
boost::mutex::scoped_lock l(m_ses->m_mutex);
|
||||||
torrent* t = m_ses->find_torrent(m_info_hash);
|
torrent* t = m_ses->find_torrent(m_info_hash);
|
||||||
if (t != 0)
|
if (t != 0) t->set_tracker_login(name, password);
|
||||||
{
|
|
||||||
t->set_tracker_login(name, password);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_chk)
|
if (m_chk)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock l(m_chk->m_mutex);
|
boost::mutex::scoped_lock l(m_chk->m_mutex);
|
||||||
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||||
if (d != 0)
|
if (d != 0) d->torrent_ptr->set_tracker_login(name, password);
|
||||||
{
|
|
||||||
d->torrent_ptr->set_tracker_login(name, password);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw invalid_handle();
|
throw invalid_handle();
|
||||||
|
@ -467,8 +459,15 @@ namespace libtorrent
|
||||||
p.total_download = statistics.total_payload_download();
|
p.total_download = statistics.total_payload_download();
|
||||||
p.total_upload = statistics.total_payload_upload();
|
p.total_upload = statistics.total_payload_upload();
|
||||||
|
|
||||||
p.upload_limit = peer->send_quota();
|
if (peer->upload_bandwidth.given == std::numeric_limits<int>::max())
|
||||||
p.upload_ceiling = peer->send_quota_limit();
|
p.upload_limit = -1;
|
||||||
|
else
|
||||||
|
p.upload_limit = peer->upload_bandwidth.given;
|
||||||
|
|
||||||
|
if (peer->upload_bandwidth.wanted == std::numeric_limits<int>::max())
|
||||||
|
p.upload_ceiling = -1;
|
||||||
|
else
|
||||||
|
p.upload_ceiling = peer->upload_bandwidth.wanted;
|
||||||
|
|
||||||
p.load_balancing = peer->total_free_upload();
|
p.load_balancing = peer->total_free_upload();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue