replaced the bandwidth throttling code with a leaky bucket for better accuracy
This commit is contained in:
parent
5f6c12214b
commit
87f7b186b0
|
@ -1,3 +1,4 @@
|
|||
* Improved the bandwidth limiter (it now implements a leaky bucket).
|
||||
* Improved the HTTP seed downloader to report accurate progress.
|
||||
* Added more client peer-id signatures to be recognized.
|
||||
* added support for HTTP servers that skip the CR before the NL at line breaks.
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -32,6 +32,7 @@ feature.compose <dht-support>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ;
|
|||
SOURCES =
|
||||
allocate_resources.cpp
|
||||
alert.cpp
|
||||
bandwidth_manager.cpp
|
||||
entry.cpp
|
||||
escape_string.cpp
|
||||
file.cpp
|
||||
|
|
|
@ -229,18 +229,15 @@ std::string progress_bar(float progress, int width, char const* code = "33")
|
|||
return std::string(bar.begin(), bar.end());
|
||||
}
|
||||
|
||||
char const* peer_index(libtorrent::tcp::endpoint addr, std::vector<libtorrent::peer_info> const& peers)
|
||||
int peer_index(libtorrent::tcp::endpoint addr, std::vector<libtorrent::peer_info> const& peers)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
std::vector<peer_info>::const_iterator i = std::find_if(peers.begin()
|
||||
, peers.end(), boost::bind(std::equal_to<libtorrent::tcp::endpoint>()
|
||||
, bind(&peer_info::ip, _1), addr));
|
||||
if (i == peers.end()) return "+";
|
||||
if (i == peers.end()) return -1;
|
||||
|
||||
static char str[] = " ";
|
||||
int index = i - peers.begin();
|
||||
str[0] = (index < 10)?'0' + index:'A' + index - 10;
|
||||
return str;
|
||||
return i - peers.begin();
|
||||
}
|
||||
|
||||
void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const& peers)
|
||||
|
@ -909,14 +906,21 @@ int main(int ac, char* av[])
|
|||
out << i->piece_index << ": [";
|
||||
for (int j = 0; j < i->blocks_in_piece; ++j)
|
||||
{
|
||||
char const* peer_str = peer_index(i->peer[j], peers);
|
||||
int index = peer_index(i->peer[j], peers);
|
||||
static char str[] = "+";
|
||||
if (index >= 0)
|
||||
str[0] = (index < 10)?'0' + index:'A' + index - 10;
|
||||
|
||||
#ifdef ANSI_TERMINAL_COLORS
|
||||
if (i->finished_blocks[j]) out << esc("32;7") << peer_str << esc("0");
|
||||
else if (i->requested_blocks[j]) out << peer_str;
|
||||
if (peers[index].downloading_piece_index == i->piece_index
|
||||
&& peers[index].downloading_block_index == j)
|
||||
out << esc("33;7") << str << esc("0");
|
||||
else if (i->finished_blocks[j]) out << esc("32;7") << str << esc("0");
|
||||
else if (i->requested_blocks[j]) out << str;
|
||||
else out << "-";
|
||||
#else
|
||||
if (i->finished_blocks[j]) out << "#";
|
||||
else if (i->requested_blocks[j]) out << peer_str;
|
||||
else if (i->requested_blocks[j]) out << str;
|
||||
else out << "-";
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
nobase_include_HEADERS = libtorrent/alert.hpp \
|
||||
libtorrent/alert_types.hpp \
|
||||
libtorrent/allocate_resources.hpp \
|
||||
libtorrent/bandwidth_manager.hpp \
|
||||
libtorrent/bencode.hpp \
|
||||
libtorrent/buffer.hpp \
|
||||
libtorrent/config.hpp \
|
||||
|
|
|
@ -76,6 +76,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/stat.hpp"
|
||||
#include "libtorrent/file_pool.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -282,6 +283,13 @@ namespace libtorrent
|
|||
io_service m_io_service;
|
||||
asio::strand m_strand;
|
||||
|
||||
// the bandwidth manager is responsible for
|
||||
// handing out bandwidth to connections that
|
||||
// asks for it, it can also throttle the
|
||||
// rate.
|
||||
bandwidth_manager m_dl_bandwidth_manager;
|
||||
bandwidth_manager m_ul_bandwidth_manager;
|
||||
|
||||
tracker_manager m_tracker_manager;
|
||||
torrent_map m_torrents;
|
||||
|
||||
|
@ -331,11 +339,6 @@ namespace libtorrent
|
|||
// should exit
|
||||
volatile bool m_abort;
|
||||
|
||||
// maximum upload rate given in
|
||||
// bytes per second. -1 means
|
||||
// unlimited
|
||||
int m_upload_rate;
|
||||
int m_download_rate;
|
||||
int m_max_uploads;
|
||||
int m_max_connections;
|
||||
// the number of simultaneous half-open tcp
|
||||
|
|
|
@ -71,6 +71,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/piece_block_progress.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
|
||||
// TODO: each time a block is 'taken over'
|
||||
// from another peer. That peer must be given
|
||||
|
@ -102,6 +103,13 @@ namespace libtorrent
|
|||
friend void intrusive_ptr_release(peer_connection const*);
|
||||
public:
|
||||
|
||||
enum channels
|
||||
{
|
||||
upload_channel,
|
||||
download_channel,
|
||||
num_channels
|
||||
};
|
||||
|
||||
// this is the constructor where the we are the active part.
|
||||
// The peer_conenction should handshake and verify that the
|
||||
// other end has the correct id
|
||||
|
@ -285,10 +293,13 @@ namespace libtorrent
|
|||
void cancel_request(piece_block const& b);
|
||||
void send_block_requests();
|
||||
|
||||
// how much bandwidth we're using, how much we want,
|
||||
// and how much we are allowed to use.
|
||||
resource_request m_ul_bandwidth_quota;
|
||||
resource_request m_dl_bandwidth_quota;
|
||||
int max_assignable_bandwidth(int channel) const
|
||||
{
|
||||
return m_bandwidth_limit[channel].max_assignable();
|
||||
}
|
||||
|
||||
void assign_bandwidth(int channel, int amount);
|
||||
void expire_bandwidth(int channel, int amount);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const;
|
||||
|
@ -365,6 +376,10 @@ namespace libtorrent
|
|||
|
||||
bool verify_piece(peer_request const& p) const;
|
||||
|
||||
// the bandwidth channels, upload and download
|
||||
// keeps track of the current quotas
|
||||
bandwidth_limit m_bandwidth_limit[num_channels];
|
||||
|
||||
// statistics about upload and download speeds
|
||||
// and total amount of uploads and downloads for
|
||||
// this peer
|
||||
|
|
|
@ -337,6 +337,9 @@ namespace libtorrent
|
|||
// the required popularity of a piece in order to download
|
||||
// it in sequence instead of random order.
|
||||
int m_sequenced_download_threshold;
|
||||
#ifndef NDEBUG
|
||||
bool m_files_checked_called;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline int piece_picker::blocks_in_piece(int index) const
|
||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
|
@ -66,6 +67,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/piece_picker.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -188,6 +190,17 @@ namespace libtorrent
|
|||
float ratio() const
|
||||
{ return m_ratio; }
|
||||
|
||||
// --------------------------------------------
|
||||
// BANDWIDTH MANAGEMENT
|
||||
|
||||
bandwidth_limit m_bandwidth_limit[2];
|
||||
|
||||
void request_bandwidth(int channel
|
||||
, boost::intrusive_ptr<peer_connection> p);
|
||||
|
||||
void expire_bandwidth(int channel, int amount);
|
||||
void assign_bandwidth(int channel, int amount);
|
||||
|
||||
// --------------------------------------------
|
||||
// PEER MANAGEMENT
|
||||
|
||||
|
@ -413,12 +426,8 @@ namespace libtorrent
|
|||
// --------------------------------------------
|
||||
// RESOURCE MANAGEMENT
|
||||
|
||||
// this will distribute the given upload/download
|
||||
// quotas and number of connections, among the peers
|
||||
void distribute_resources(float tick_interval);
|
||||
|
||||
resource_request m_ul_bandwidth_quota;
|
||||
resource_request m_dl_bandwidth_quota;
|
||||
resource_request m_uploads_quota;
|
||||
resource_request m_connections_quota;
|
||||
|
||||
|
@ -536,6 +545,9 @@ namespace libtorrent
|
|||
|
||||
boost::scoped_ptr<piece_picker> m_picker;
|
||||
|
||||
// the queue of peer_connections that want more bandwidth
|
||||
std::deque<intrusive_ptr<peer_connection> > m_bandwidth_queue[2];
|
||||
|
||||
std::vector<announce_entry> m_trackers;
|
||||
// this is an index into m_torrent_file.trackers()
|
||||
int m_last_working_tracker;
|
||||
|
@ -585,20 +597,6 @@ namespace libtorrent
|
|||
// are opened through
|
||||
tcp::endpoint m_net_interface;
|
||||
|
||||
// the max number of bytes this torrent
|
||||
// can upload per second
|
||||
int m_upload_bandwidth_limit;
|
||||
int m_download_bandwidth_limit;
|
||||
|
||||
// the accumulated excess upload and download
|
||||
// bandwidth used. Used to balance out the
|
||||
// bandwidth to match the limit over time
|
||||
int m_excess_ul;
|
||||
int m_excess_dl;
|
||||
|
||||
int m_soft_ul_limit;
|
||||
int m_soft_dl_limit;
|
||||
|
||||
boost::filesystem::path m_save_path;
|
||||
|
||||
// determines the storage state for this torrent.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
lib_LTLIBRARIES = libtorrent.la
|
||||
|
||||
libtorrent_la_SOURCES = allocate_resources.cpp \
|
||||
entry.cpp escape_string.cpp \
|
||||
bandwidth_manager.cpp entry.cpp escape_string.cpp \
|
||||
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
|
||||
piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp stat.cpp \
|
||||
storage.cpp torrent.cpp torrent_handle.cpp \
|
||||
|
@ -26,6 +26,7 @@ $(top_srcdir)/include/libtorrent/alert_types.hpp \
|
|||
$(top_srcdir)/include/libtorrent/allocate_resources.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
|
||||
$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
|
||||
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
||||
$(top_srcdir)/include/libtorrent/buffer.hpp \
|
||||
$(top_srcdir)/include/libtorrent/debug.hpp \
|
||||
|
|
|
@ -132,6 +132,14 @@ namespace libtorrent
|
|||
// we have to wait for the handshake to see
|
||||
// which torrent the connector want's to connect to
|
||||
|
||||
|
||||
// upload bandwidth will only be given to connections
|
||||
// that are part of a torrent. Since this is an incoming
|
||||
// connection, we have to give it some initial bandwidth
|
||||
// to send the handshake.
|
||||
m_bandwidth_limit[download_channel].assign(80);
|
||||
m_bandwidth_limit[upload_channel].assign(80);
|
||||
|
||||
// start in the state where we are trying to read the
|
||||
// handshake from the other side
|
||||
reset_recv_buffer(1);
|
||||
|
@ -178,15 +186,15 @@ namespace libtorrent
|
|||
p.total_download = statistics().total_payload_download();
|
||||
p.total_upload = statistics().total_payload_upload();
|
||||
|
||||
if (m_ul_bandwidth_quota.given == std::numeric_limits<int>::max())
|
||||
if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf)
|
||||
p.upload_limit = -1;
|
||||
else
|
||||
p.upload_limit = m_ul_bandwidth_quota.given;
|
||||
p.upload_limit = m_bandwidth_limit[upload_channel].throttle();
|
||||
|
||||
if (m_dl_bandwidth_quota.given == std::numeric_limits<int>::max())
|
||||
if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf)
|
||||
p.download_limit = -1;
|
||||
else
|
||||
p.download_limit = m_dl_bandwidth_quota.given;
|
||||
p.download_limit = m_bandwidth_limit[download_channel].throttle();
|
||||
|
||||
p.load_balancing = total_free_upload();
|
||||
|
||||
|
|
|
@ -131,63 +131,6 @@ namespace libtorrent
|
|||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
assert(t);
|
||||
// these numbers are used the first second of connection.
|
||||
// then the given upload limits will be applied by running
|
||||
// allocate_resources().
|
||||
m_ul_bandwidth_quota.min = 10;
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
if (t->m_ul_bandwidth_quota.given == resource_request::inf)
|
||||
{
|
||||
m_ul_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->num_peers() == 0)
|
||||
{
|
||||
// just enough to get started with the handshake and bitmask
|
||||
m_ul_bandwidth_quota.given = 400;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set the limit of this new connection to the mean of the other connections
|
||||
size_type total_ul_given = 0;
|
||||
for (torrent::peer_iterator i = t->begin()
|
||||
, end(t->end()); i != end; ++i)
|
||||
{
|
||||
total_ul_given += i->second->m_ul_bandwidth_quota.given;
|
||||
}
|
||||
m_ul_bandwidth_quota.given = total_ul_given / t->num_peers();
|
||||
}
|
||||
}
|
||||
|
||||
m_dl_bandwidth_quota.min = 10;
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
if (t->m_dl_bandwidth_quota.given == resource_request::inf)
|
||||
{
|
||||
m_dl_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->num_peers() == 0)
|
||||
{
|
||||
// just enough to get started with the handshake and bitmask
|
||||
m_dl_bandwidth_quota.given = 400;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set the limit of this new connection to the mean of the other connections
|
||||
size_type total_dl_given = 0;
|
||||
for (torrent::peer_iterator i = t->begin()
|
||||
, end(t->end()); i != end; ++i)
|
||||
{
|
||||
total_dl_given += i->second->m_dl_bandwidth_quota.given;
|
||||
}
|
||||
m_dl_bandwidth_quota.given = total_dl_given / t->num_peers();
|
||||
}
|
||||
}
|
||||
|
||||
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
|
||||
|
||||
if (t->ready_for_connections())
|
||||
|
@ -250,24 +193,7 @@ namespace libtorrent
|
|||
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
|
||||
(*m_logger) << "*** INCOMING CONNECTION\n";
|
||||
#endif
|
||||
|
||||
|
||||
// upload bandwidth will only be given to connections
|
||||
// that are part of a torrent. Since this is an incoming
|
||||
// connection, we have to give it some initial bandwidth
|
||||
// to send the handshake.
|
||||
// after one second, allocate_resources() will be called
|
||||
// and the correct bandwidth limits will be set on all
|
||||
// connections.
|
||||
|
||||
m_ul_bandwidth_quota.min = 10;
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
m_ul_bandwidth_quota.given = 400;
|
||||
|
||||
m_dl_bandwidth_quota.min = 10;
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
m_dl_bandwidth_quota.given = 400;
|
||||
|
||||
|
||||
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
|
||||
}
|
||||
|
||||
|
@ -278,7 +204,6 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void peer_connection::init()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -467,16 +392,6 @@ namespace libtorrent
|
|||
m_free_upload += free_upload;
|
||||
}
|
||||
|
||||
void peer_connection::reset_upload_quota()
|
||||
{
|
||||
m_ul_bandwidth_quota.reset();
|
||||
m_dl_bandwidth_quota.reset();
|
||||
assert(m_ul_bandwidth_quota.left() >= 0);
|
||||
assert(m_dl_bandwidth_quota.left() >= 0);
|
||||
setup_send();
|
||||
setup_receive();
|
||||
}
|
||||
|
||||
// verifies a piece to see if it is valid (is within a valid range)
|
||||
// and if it can correspond to a request generated by libtorrent.
|
||||
bool peer_connection::verify_piece(const peer_request& p) const
|
||||
|
@ -1560,6 +1475,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(packet_size > 0);
|
||||
assert((int)m_recv_buffer.size() >= size);
|
||||
|
||||
std::copy(m_recv_buffer.begin() + size, m_recv_buffer.begin() + m_recv_pos, m_recv_buffer.begin());
|
||||
|
@ -1658,33 +1574,12 @@ namespace libtorrent
|
|||
// maintain the share ratio given by m_ratio
|
||||
// with all peers.
|
||||
|
||||
if (has_peer_choked() || !is_interesting())
|
||||
{
|
||||
// if the peer choked us, we can't download
|
||||
// any data anyway, limit the max download
|
||||
// bandwidth. If we're a seed, it doesn't matter,
|
||||
// we won't be interested in downloading anyway
|
||||
m_dl_bandwidth_quota.max = 400;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
}
|
||||
|
||||
if (t->is_seed() || is_choked() || t->ratio() == 0.0f)
|
||||
{
|
||||
// if we have downloaded more than one piece more
|
||||
// than we have uploaded OR if we are a seed
|
||||
// have an unlimited upload rate
|
||||
// the exception is if we have choked the peer, and
|
||||
// we have a limited amount of upload bandwidth, then
|
||||
// we set the max to 400, just enough for the
|
||||
// protocol chatter.
|
||||
if (is_choked()
|
||||
&& m_ul_bandwidth_quota.given < resource_request::inf)
|
||||
m_ul_bandwidth_quota.max = 400;
|
||||
else
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
m_bandwidth_limit[upload_channel].throttle(bandwidth_limit::inf);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1707,17 +1602,10 @@ namespace libtorrent
|
|||
upload_speed_limit = std::min(upload_speed_limit,
|
||||
(double)std::numeric_limits<int>::max());
|
||||
|
||||
m_ul_bandwidth_quota.max
|
||||
= std::max((int)upload_speed_limit, m_ul_bandwidth_quota.min);
|
||||
m_bandwidth_limit[upload_channel].throttle(
|
||||
std::min(std::max((int)upload_speed_limit, 20)
|
||||
, m_upload_limit));
|
||||
}
|
||||
if (m_ul_bandwidth_quota.given > m_ul_bandwidth_quota.max)
|
||||
m_ul_bandwidth_quota.given = m_ul_bandwidth_quota.max;
|
||||
|
||||
if (m_upload_limit < m_ul_bandwidth_quota.max)
|
||||
m_ul_bandwidth_quota.max = m_upload_limit;
|
||||
|
||||
if (m_download_limit < m_dl_bandwidth_quota.max)
|
||||
m_dl_bandwidth_quota.max = m_download_limit;
|
||||
|
||||
fill_send_buffer();
|
||||
/*
|
||||
|
@ -1808,6 +1696,38 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void peer_connection::assign_bandwidth(int channel, int amount)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "bandwidth [ " << channel << " ] + " << amount << "\n";
|
||||
#endif
|
||||
|
||||
m_bandwidth_limit[channel].assign(amount);
|
||||
if (channel == upload_channel)
|
||||
{
|
||||
m_writing = false;
|
||||
setup_send();
|
||||
}
|
||||
else if (channel == download_channel)
|
||||
{
|
||||
m_reading = false;
|
||||
setup_receive();
|
||||
}
|
||||
}
|
||||
|
||||
void peer_connection::expire_bandwidth(int channel, int amount)
|
||||
{
|
||||
m_bandwidth_limit[channel].expire(amount);
|
||||
if (channel == upload_channel)
|
||||
{
|
||||
setup_send();
|
||||
}
|
||||
else if (channel == download_channel)
|
||||
{
|
||||
setup_receive();
|
||||
}
|
||||
}
|
||||
|
||||
void peer_connection::setup_send()
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -1815,6 +1735,31 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_writing) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (m_bandwidth_limit[upload_channel].quota_left() == 0
|
||||
&& (!m_send_buffer[m_current_send_buffer].empty()
|
||||
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
|
||||
&& !m_connecting
|
||||
&& t)
|
||||
{
|
||||
// in this case, we have data to send, but no
|
||||
// bandwidth. So, we simply request bandwidth
|
||||
// from the torrent
|
||||
assert(t);
|
||||
if (m_bandwidth_limit[upload_channel].max_assignable() > 0)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
|
||||
#endif
|
||||
|
||||
t->request_bandwidth(upload_channel, self());
|
||||
m_writing = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!can_write()) return;
|
||||
|
||||
assert(!m_writing);
|
||||
|
@ -1832,7 +1777,7 @@ namespace libtorrent
|
|||
if (!m_send_buffer[sending_buffer].empty())
|
||||
{
|
||||
int amount_to_send
|
||||
= std::min(m_ul_bandwidth_quota.left()
|
||||
= std::min(m_bandwidth_limit[upload_channel].quota_left()
|
||||
, (int)m_send_buffer[sending_buffer].size() - m_write_pos);
|
||||
|
||||
assert(amount_to_send > 0);
|
||||
|
@ -1853,23 +1798,41 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_reading) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (m_bandwidth_limit[download_channel].quota_left() == 0
|
||||
&& !m_connecting
|
||||
&& t)
|
||||
{
|
||||
assert(t);
|
||||
if (m_bandwidth_limit[download_channel].max_assignable() > 0)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
||||
#endif
|
||||
t->request_bandwidth(download_channel, self());
|
||||
m_reading = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!can_read()) return;
|
||||
|
||||
assert(m_packet_size > 0);
|
||||
int max_receive = std::min(
|
||||
m_dl_bandwidth_quota.left()
|
||||
m_bandwidth_limit[download_channel].quota_left()
|
||||
, m_packet_size - m_recv_pos);
|
||||
assert(max_receive > 0);
|
||||
|
||||
assert(m_recv_pos >= 0);
|
||||
assert(m_packet_size > 0);
|
||||
assert(m_dl_bandwidth_quota.left() > 0);
|
||||
assert(max_receive > 0);
|
||||
|
||||
assert(can_read());
|
||||
m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||
, max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2));
|
||||
m_reading = true;
|
||||
assert(m_dl_bandwidth_quota.used <= m_dl_bandwidth_quota.given);
|
||||
}
|
||||
|
||||
void peer_connection::reset_recv_buffer(int packet_size)
|
||||
|
@ -1925,7 +1888,7 @@ namespace libtorrent
|
|||
assert(m_reading);
|
||||
m_reading = false;
|
||||
// correct the dl quota usage, if not all of the buffer was actually read
|
||||
m_dl_bandwidth_quota.used += bytes_transferred;
|
||||
m_bandwidth_limit[download_channel].use_quota(bytes_transferred);
|
||||
|
||||
if (error)
|
||||
{
|
||||
|
@ -2004,7 +1967,7 @@ namespace libtorrent
|
|||
// we want to send data
|
||||
return (!m_send_buffer[m_current_send_buffer].empty()
|
||||
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
|
||||
&& m_ul_bandwidth_quota.left() > 0
|
||||
&& m_bandwidth_limit[upload_channel].quota_left() > 0
|
||||
&& !m_connecting;
|
||||
}
|
||||
|
||||
|
@ -2012,7 +1975,8 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
return m_dl_bandwidth_quota.left() > 0 && !m_connecting;
|
||||
return m_bandwidth_limit[download_channel].quota_left() > 0
|
||||
&& !m_connecting;
|
||||
}
|
||||
|
||||
void peer_connection::connect()
|
||||
|
@ -2069,6 +2033,7 @@ namespace libtorrent
|
|||
m_connecting = false;
|
||||
on_connected();
|
||||
setup_send();
|
||||
setup_receive();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
|
@ -2097,8 +2062,8 @@ namespace libtorrent
|
|||
|
||||
assert(m_writing);
|
||||
m_writing = false;
|
||||
// correct the ul quota usage, if not all of the buffer was sent
|
||||
m_ul_bandwidth_quota.used += bytes_transferred;
|
||||
|
||||
m_bandwidth_limit[upload_channel].use_quota(bytes_transferred);
|
||||
m_write_pos += bytes_transferred;
|
||||
|
||||
if (error)
|
||||
|
|
|
@ -62,6 +62,9 @@ namespace libtorrent
|
|||
{
|
||||
assert(blocks_per_piece > 0);
|
||||
assert(total_num_blocks >= 0);
|
||||
#ifndef NDEBUG
|
||||
m_files_checked_called = false;
|
||||
#endif
|
||||
|
||||
// the piece index is stored in 20 bits, which limits the allowed
|
||||
// number of pieces somewhat
|
||||
|
@ -87,6 +90,9 @@ namespace libtorrent
|
|||
const std::vector<bool>& pieces
|
||||
, const std::vector<downloading_piece>& unfinished)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
m_files_checked_called = true;
|
||||
#endif
|
||||
// build a vector of all the pieces we don't have
|
||||
std::vector<int> piece_list;
|
||||
piece_list.reserve(std::count(pieces.begin(), pieces.end(), false));
|
||||
|
@ -423,6 +429,7 @@ namespace libtorrent
|
|||
assert(elem_index != piece_pos::we_have_index);
|
||||
std::vector<std::vector<int> >& src_vec(pick_piece_info_vector(
|
||||
downloading, filtered));
|
||||
assert(m_files_checked_called);
|
||||
|
||||
assert((int)src_vec.size() > priority);
|
||||
assert((int)src_vec[priority].size() > elem_index);
|
||||
|
@ -537,6 +544,7 @@ namespace libtorrent
|
|||
assert(!filtered);
|
||||
assert(priority >= 0);
|
||||
assert(elem_index >= 0);
|
||||
assert(m_files_checked_called);
|
||||
|
||||
std::vector<std::vector<int> >& src_vec(pick_piece_info_vector(downloading, filtered));
|
||||
|
||||
|
@ -588,6 +596,7 @@ namespace libtorrent
|
|||
|
||||
assert(index >= 0);
|
||||
assert(index < (int)m_piece_map.size());
|
||||
assert(m_files_checked_called);
|
||||
|
||||
assert(m_piece_map[index].downloading == 1);
|
||||
|
||||
|
@ -609,6 +618,7 @@ namespace libtorrent
|
|||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
assert(i >= 0);
|
||||
assert(i < (int)m_piece_map.size());
|
||||
assert(m_files_checked_called);
|
||||
|
||||
int index = m_piece_map[i].index;
|
||||
int prev_priority = m_piece_map[i].priority(m_sequenced_download_threshold);
|
||||
|
@ -636,6 +646,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
||||
assert(m_files_checked_called);
|
||||
assert(i >= 0);
|
||||
assert(i < (int)m_piece_map.size());
|
||||
|
||||
|
@ -758,6 +769,7 @@ namespace libtorrent
|
|||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
assert(num_blocks > 0);
|
||||
assert(pieces.size() == m_piece_map.size());
|
||||
assert(m_files_checked_called);
|
||||
|
||||
// free refers to pieces that are free to download, no one else
|
||||
// is downloading them.
|
||||
|
|
|
@ -476,12 +476,12 @@ namespace libtorrent { namespace detail
|
|||
, fingerprint const& cl_fprint
|
||||
, char const* listen_interface)
|
||||
: m_strand(m_io_service)
|
||||
, m_dl_bandwidth_manager(m_io_service, peer_connection::download_channel)
|
||||
, m_ul_bandwidth_manager(m_io_service, peer_connection::upload_channel)
|
||||
, m_tracker_manager(m_settings)
|
||||
, m_listen_port_range(listen_port_range)
|
||||
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
||||
, m_abort(false)
|
||||
, m_upload_rate(-1)
|
||||
, m_download_rate(-1)
|
||||
, m_max_uploads(-1)
|
||||
, m_max_connections(-1)
|
||||
, m_half_open_limit(-1)
|
||||
|
@ -505,6 +505,8 @@ namespace libtorrent { namespace detail
|
|||
"3. hard download quota\n"
|
||||
"\n";
|
||||
m_second_counter = 0;
|
||||
m_dl_bandwidth_manager.m_ses = this;
|
||||
m_ul_bandwidth_manager.m_ses = this;
|
||||
#endif
|
||||
|
||||
// ---- generate a peer id ----
|
||||
|
@ -560,7 +562,7 @@ namespace libtorrent { namespace detail
|
|||
assert(!m_abort);
|
||||
// abort the main thread
|
||||
m_abort = true;
|
||||
m_io_service.interrupt();
|
||||
m_io_service.stop();
|
||||
l.unlock();
|
||||
|
||||
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
||||
|
@ -895,7 +897,7 @@ namespace libtorrent { namespace detail
|
|||
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
|
||||
#endif
|
||||
m_abort = true;
|
||||
m_io_service.interrupt();
|
||||
m_io_service.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -976,29 +978,9 @@ namespace libtorrent { namespace detail
|
|||
|
||||
// distribute the maximum upload rate among the torrents
|
||||
|
||||
assert(m_upload_rate >= -1);
|
||||
assert(m_download_rate >= -1);
|
||||
assert(m_max_uploads >= -1);
|
||||
assert(m_max_connections >= -1);
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_stats_logger) << m_second_counter++ << "\t"
|
||||
<< (m_upload_rate == -1 ? m_upload_rate
|
||||
: int(m_upload_rate * tick_interval)) << "\n";
|
||||
#endif
|
||||
|
||||
allocate_resources(m_upload_rate == -1
|
||||
? std::numeric_limits<int>::max()
|
||||
: int(m_upload_rate * tick_interval)
|
||||
, m_torrents
|
||||
, &torrent::m_ul_bandwidth_quota);
|
||||
|
||||
allocate_resources(m_download_rate == -1
|
||||
? std::numeric_limits<int>::max()
|
||||
: int(m_download_rate * tick_interval)
|
||||
, m_torrents
|
||||
, &torrent::m_dl_bandwidth_quota);
|
||||
|
||||
allocate_resources(m_max_uploads == -1
|
||||
? std::numeric_limits<int>::max()
|
||||
: m_max_uploads
|
||||
|
@ -1115,7 +1097,7 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
tracker_timer.expires_from_now(boost::posix_time::milliseconds(100));
|
||||
tracker_timer.async_wait(m_strand.wrap(
|
||||
bind(&io_service::interrupt, &m_io_service)));
|
||||
bind(&io_service::stop, &m_io_service)));
|
||||
|
||||
m_io_service.reset();
|
||||
m_io_service.run();
|
||||
|
@ -1570,8 +1552,10 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_download_rate = bytes_per_second;
|
||||
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
|
||||
m_dl_bandwidth_manager.throttle(bytes_per_second);
|
||||
}
|
||||
|
||||
bool session_impl::is_listening() const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -1584,7 +1568,7 @@ namespace libtorrent { namespace detail
|
|||
// lock the main thread and abort it
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_abort = true;
|
||||
m_io_service.interrupt();
|
||||
m_io_service.stop();
|
||||
}
|
||||
m_thread->join();
|
||||
|
||||
|
@ -1640,7 +1624,8 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_upload_rate = bytes_per_second;
|
||||
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
|
||||
m_ul_bandwidth_manager.throttle(bytes_per_second);
|
||||
}
|
||||
|
||||
int session_impl::num_uploads() const
|
||||
|
@ -1679,13 +1664,13 @@ namespace libtorrent { namespace detail
|
|||
int session_impl::upload_rate_limit() const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
return m_upload_rate;
|
||||
return m_ul_bandwidth_manager.throttle();
|
||||
}
|
||||
|
||||
int session_impl::download_rate_limit() const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
return m_download_rate;
|
||||
return m_dl_bandwidth_manager.throttle();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -1711,9 +1696,6 @@ namespace libtorrent { namespace detail
|
|||
error_log << "peer_connection::is_connecting() " << p->is_connecting() << "\n";
|
||||
error_log << "peer_connection::can_write() " << p->can_write() << "\n";
|
||||
error_log << "peer_connection::can_read() " << p->can_read() << "\n";
|
||||
error_log << "peer_connection::ul_quota_left " << p->m_ul_bandwidth_quota.left() << "\n";
|
||||
error_log << "peer_connection::dl_quota_left " << p->m_dl_bandwidth_quota.left() << "\n";
|
||||
error_log << "peer_connection::m_ul_bandwidth_quota.given " << p->m_ul_bandwidth_quota.given << "\n";
|
||||
error_log << "peer_connection::get_peer_id " << p->pid() << "\n";
|
||||
error_log << "place: " << place << "\n";
|
||||
error_log.flush();
|
||||
|
|
286
src/torrent.cpp
286
src/torrent.cpp
|
@ -258,12 +258,6 @@ namespace libtorrent
|
|||
, m_total_failed_bytes(0)
|
||||
, m_total_redundant_bytes(0)
|
||||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_download_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_excess_ul(0)
|
||||
, m_excess_dl(0)
|
||||
, m_soft_ul_limit(10000)
|
||||
, m_soft_dl_limit(10000)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_compact_mode(compact_mode)
|
||||
, m_default_block_size(block_size)
|
||||
|
@ -294,33 +288,6 @@ namespace libtorrent
|
|||
// this will be corrected the next time the main session
|
||||
// distributes resources, i.e. on average in 0.5 seconds
|
||||
m_connections_quota.given = 100;
|
||||
m_uploads_quota.max = std::numeric_limits<int>::max();
|
||||
m_connections_quota.max = std::numeric_limits<int>::max();
|
||||
|
||||
m_dl_bandwidth_quota.min = 100;
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
if (m_ses.m_download_rate == -1)
|
||||
{
|
||||
m_dl_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dl_bandwidth_quota.given = 400;
|
||||
}
|
||||
|
||||
m_ul_bandwidth_quota.min = 100;
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
if (m_ses.m_upload_rate == -1)
|
||||
{
|
||||
m_ul_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ul_bandwidth_quota.given = 400;
|
||||
}
|
||||
|
||||
m_policy.reset(new policy(this));
|
||||
init();
|
||||
|
||||
|
@ -375,12 +342,6 @@ namespace libtorrent
|
|||
, m_total_failed_bytes(0)
|
||||
, m_total_redundant_bytes(0)
|
||||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_download_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_excess_ul(0)
|
||||
, m_excess_dl(0)
|
||||
, m_soft_ul_limit(10000)
|
||||
, m_soft_dl_limit(10000)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_compact_mode(compact_mode)
|
||||
, m_default_block_size(block_size)
|
||||
|
@ -412,32 +373,6 @@ namespace libtorrent
|
|||
m_connections_quota.given = 100;
|
||||
m_uploads_quota.max = std::numeric_limits<int>::max();
|
||||
m_connections_quota.max = std::numeric_limits<int>::max();
|
||||
|
||||
m_dl_bandwidth_quota.min = 100;
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
if (m_ses.m_download_rate == -1)
|
||||
{
|
||||
m_dl_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dl_bandwidth_quota.given = 400;
|
||||
}
|
||||
|
||||
m_ul_bandwidth_quota.min = 100;
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
|
||||
if (m_ses.m_upload_rate == -1)
|
||||
{
|
||||
m_ul_bandwidth_quota.given = resource_request::inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ul_bandwidth_quota.given = 400;
|
||||
}
|
||||
|
||||
m_trackers.push_back(announce_entry(tracker_url));
|
||||
|
||||
m_policy.reset(new policy(this));
|
||||
|
@ -1297,12 +1232,6 @@ namespace libtorrent
|
|||
boost::shared_ptr<stream_socket> s(new stream_socket(m_ses.m_io_service));
|
||||
boost::intrusive_ptr<peer_connection> c(new web_peer_connection(
|
||||
m_ses, shared_from_this(), s, a, url));
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_ses.m_logger) << "add url seed (" << c->m_dl_bandwidth_quota.given << ", "
|
||||
<< c->m_dl_bandwidth_quota.used << ") ";
|
||||
(*m_ses.m_logger) << "\n";
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
|
@ -1359,13 +1288,6 @@ namespace libtorrent
|
|||
boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
|
||||
m_ses, shared_from_this(), s, a));
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_ses.m_logger) << "connect_to_peer (" << c->m_dl_bandwidth_quota.given << ", "
|
||||
<< c->m_dl_bandwidth_quota.used << ") ";
|
||||
(*m_ses.m_logger) << "\n";
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
#endif
|
||||
|
@ -1530,6 +1452,47 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void torrent::request_bandwidth(int channel
|
||||
, boost::intrusive_ptr<peer_connection> p)
|
||||
{
|
||||
if (m_bandwidth_limit[channel].max_assignable() >= 17000)
|
||||
{
|
||||
if (channel == peer_connection::upload_channel)
|
||||
m_ses.m_ul_bandwidth_manager.request_bandwidth(p);
|
||||
else if (channel == peer_connection::download_channel)
|
||||
m_ses.m_dl_bandwidth_manager.request_bandwidth(p);
|
||||
m_bandwidth_limit[channel].assign(17000);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bandwidth_queue[channel].push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::expire_bandwidth(int channel, int amount)
|
||||
{
|
||||
assert(amount >= -1);
|
||||
if (amount == -1) amount = 17000;
|
||||
m_bandwidth_limit[channel].expire(amount);
|
||||
|
||||
while (!m_bandwidth_queue[channel].empty() && m_bandwidth_limit[channel].max_assignable() >= 17000)
|
||||
{
|
||||
intrusive_ptr<peer_connection> p = m_bandwidth_queue[channel].front();
|
||||
m_bandwidth_queue[channel].pop_front();
|
||||
if (channel == peer_connection::upload_channel)
|
||||
m_ses.m_ul_bandwidth_manager.request_bandwidth(p);
|
||||
else if (channel == peer_connection::download_channel)
|
||||
m_ses.m_dl_bandwidth_manager.request_bandwidth(p);
|
||||
m_bandwidth_limit[channel].assign(17000);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::assign_bandwidth(int channel, int amount)
|
||||
{
|
||||
assert(amount >= 0);
|
||||
if (amount < 17000) expire_bandwidth(channel, 17000 - amount);
|
||||
}
|
||||
|
||||
// called when torrent is finished (all interested pieces downloaded)
|
||||
void torrent::finished()
|
||||
{
|
||||
|
@ -1871,7 +1834,7 @@ namespace libtorrent
|
|||
assert(limit >= -1);
|
||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||
m_upload_bandwidth_limit = limit;
|
||||
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
|
||||
}
|
||||
|
||||
void torrent::set_download_limit(int limit)
|
||||
|
@ -1879,7 +1842,7 @@ namespace libtorrent
|
|||
assert(limit >= -1);
|
||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||
m_download_bandwidth_limit = limit;
|
||||
m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
|
||||
}
|
||||
|
||||
void torrent::pause()
|
||||
|
@ -1937,14 +1900,6 @@ namespace libtorrent
|
|||
m_connections_quota.used = (int)m_connections.size();
|
||||
m_uploads_quota.used = m_policy->num_uploads();
|
||||
|
||||
m_ul_bandwidth_quota.used = 0;
|
||||
m_ul_bandwidth_quota.max = 0;
|
||||
m_ul_bandwidth_quota.min = 0;
|
||||
|
||||
m_dl_bandwidth_quota.used = 0;
|
||||
m_dl_bandwidth_quota.min = 0;
|
||||
m_dl_bandwidth_quota.max = 0;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
|
@ -2005,33 +1960,7 @@ namespace libtorrent
|
|||
// updates the peer connection's ul/dl bandwidth
|
||||
// resource requests
|
||||
p->second_tick(tick_interval);
|
||||
|
||||
m_ul_bandwidth_quota.used += p->m_ul_bandwidth_quota.used;
|
||||
m_ul_bandwidth_quota.min += p->m_ul_bandwidth_quota.min;
|
||||
m_dl_bandwidth_quota.used += p->m_dl_bandwidth_quota.used;
|
||||
m_dl_bandwidth_quota.min += p->m_dl_bandwidth_quota.min;
|
||||
|
||||
m_ul_bandwidth_quota.max = saturated_add(
|
||||
m_ul_bandwidth_quota.max
|
||||
, p->m_ul_bandwidth_quota.max);
|
||||
|
||||
m_dl_bandwidth_quota.max = saturated_add(
|
||||
m_dl_bandwidth_quota.max
|
||||
, p->m_dl_bandwidth_quota.max);
|
||||
}
|
||||
|
||||
m_ul_bandwidth_quota.max
|
||||
= std::min(m_ul_bandwidth_quota.max, m_upload_bandwidth_limit);
|
||||
|
||||
if (m_upload_bandwidth_limit == resource_request::inf)
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
m_dl_bandwidth_quota.max
|
||||
= std::min(m_dl_bandwidth_quota.max, m_download_bandwidth_limit);
|
||||
|
||||
if (m_download_bandwidth_limit == resource_request::inf)
|
||||
m_dl_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
accumulator += m_stat;
|
||||
m_stat.second_tick(tick_interval);
|
||||
m_web_stat.second_tick(tick_interval);
|
||||
|
@ -2047,135 +1976,6 @@ namespace libtorrent
|
|||
m_time_scaler = 10;
|
||||
m_policy->pulse();
|
||||
}
|
||||
|
||||
assert(m_ul_bandwidth_quota.given >= 0);
|
||||
assert(m_dl_bandwidth_quota.given >= 0);
|
||||
|
||||
int ul_used = 0;
|
||||
int dl_used = 0;
|
||||
#ifdef TORRENT_LOGGING
|
||||
int ul_max = 0;
|
||||
int dl_max = 0;
|
||||
#endif
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
peer_connection* p = i->second;
|
||||
|
||||
// the bandwidth exceeding the given amount is accumulated to
|
||||
// the next timeslice, don't take it into account now as well!
|
||||
// (that would lead to a spiral of accumulating used-values)
|
||||
ul_used += std::min(p->m_ul_bandwidth_quota.used, p->m_ul_bandwidth_quota.given);
|
||||
dl_used += std::min(p->m_dl_bandwidth_quota.used, p->m_dl_bandwidth_quota.given);
|
||||
#ifdef TORRENT_LOGGING
|
||||
ul_max = saturated_add(ul_max, p->m_ul_bandwidth_quota.max);
|
||||
dl_max = saturated_add(dl_max, p->m_dl_bandwidth_quota.max);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
m_excess_ul += ul_used - m_ul_bandwidth_quota.given;
|
||||
m_excess_dl += dl_used - m_dl_bandwidth_quota.given;
|
||||
|
||||
m_excess_ul = std::max(m_excess_ul, -10000);
|
||||
m_excess_dl = std::max(m_excess_dl, -10000);
|
||||
|
||||
int ul_to_distribute = std::max(int((m_ul_bandwidth_quota.given
|
||||
- m_excess_ul * 0.7f) * 1.6f), 0);
|
||||
int dl_to_distribute = std::max(int((m_dl_bandwidth_quota.given
|
||||
- m_excess_dl * 0.7f) * 1.6f), 0);
|
||||
|
||||
m_soft_ul_limit = int(m_soft_ul_limit + (ul_to_distribute - m_soft_ul_limit) * 0.1f);
|
||||
m_soft_dl_limit = int(m_soft_dl_limit + (dl_to_distribute - m_soft_dl_limit) * 0.1f);
|
||||
|
||||
ul_to_distribute = m_soft_ul_limit;
|
||||
dl_to_distribute = m_soft_dl_limit;
|
||||
|
||||
#ifdef TORRENT_LOGGING
|
||||
std::copy(m_ul_history + 1, m_ul_history + debug_bw_history_size, m_ul_history);
|
||||
m_ul_history[debug_bw_history_size-1] = ul_used;
|
||||
std::copy(m_dl_history + 1, m_dl_history + debug_bw_history_size, m_dl_history);
|
||||
m_dl_history[debug_bw_history_size-1] = dl_used;
|
||||
|
||||
size_type mean_ul = 0;
|
||||
size_type mean_dl = 0;
|
||||
for (int i = 0; i < debug_bw_history_size; ++i)
|
||||
{
|
||||
mean_ul += m_ul_history[i];
|
||||
mean_dl += m_dl_history[i];
|
||||
}
|
||||
mean_ul /= debug_bw_history_size;
|
||||
mean_dl /= debug_bw_history_size;
|
||||
|
||||
int ul_leftovers = 0;
|
||||
int dl_leftovers = 0;
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
ul_leftovers += i->second->m_ul_bandwidth_quota.leftovers;
|
||||
dl_leftovers += i->second->m_dl_bandwidth_quota.leftovers;
|
||||
}
|
||||
|
||||
(*m_log)
|
||||
<< ul_used << "\t"
|
||||
<< mean_ul << "\t"
|
||||
<< dl_used << "\t"
|
||||
<< mean_dl << "\t"
|
||||
<< m_stat.total_payload_download() << "\t"
|
||||
<< m_web_stat.total_payload_download() << "\t"
|
||||
<< m_total_redundant_bytes
|
||||
<< "\n";
|
||||
|
||||
(*m_log)
|
||||
<< m_second_count++ << "\t"
|
||||
<< m_ul_bandwidth_quota.given << "\t"
|
||||
<< ul_to_distribute << "\t"
|
||||
<< m_excess_ul << "\t"
|
||||
<< ul_leftovers << "\t"
|
||||
<< m_dl_bandwidth_quota.given << "\t"
|
||||
<< dl_to_distribute << "\t"
|
||||
<< m_excess_dl << "\t"
|
||||
<< dl_leftovers << "\t"
|
||||
<< num_peers() << "\t"
|
||||
<< ul_max << "\t"
|
||||
<< dl_max << "\t";
|
||||
|
||||
(*m_peer_log) << m_second_count << "\t";
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
int given = i->second->m_dl_bandwidth_quota.given;
|
||||
(*m_peer_log) << (given == resource_request::inf ? -1 : given)
|
||||
<< "\t" << i->second->m_dl_bandwidth_quota.used << "\t";
|
||||
}
|
||||
for (int i = m_connections.size(); i < 10; ++i)
|
||||
{
|
||||
(*m_peer_log) << 0 << "\t" << 0 << "\t";
|
||||
}
|
||||
(*m_peer_log) << "\n";
|
||||
|
||||
#endif
|
||||
|
||||
// distribute allowed upload among the peers
|
||||
allocate_resources(ul_to_distribute
|
||||
, m_connections
|
||||
, &peer_connection::m_ul_bandwidth_quota);
|
||||
|
||||
// distribute allowed download among the peers
|
||||
allocate_resources(dl_to_distribute
|
||||
, m_connections
|
||||
, &peer_connection::m_dl_bandwidth_quota);
|
||||
|
||||
using boost::bind;
|
||||
|
||||
// tell all peers to reset their used quota. This is
|
||||
// a new second and they can again use up their quota
|
||||
|
||||
for (std::map<tcp::endpoint, peer_connection*>::iterator i
|
||||
= m_connections.begin(); i != m_connections.end(); ++i)
|
||||
{
|
||||
i->second->reset_upload_quota();
|
||||
}
|
||||
}
|
||||
|
||||
bool torrent::verify_piece(int piece_index)
|
||||
|
|
|
@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
using boost::tuples::make_tuple;
|
||||
|
|
|
@ -442,47 +442,6 @@ namespace libtorrent
|
|||
continue;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
if (!m_piece.empty())
|
||||
{
|
||||
// this is not the first partial request we get
|
||||
if (m_intermediate_piece.start + m_intermediate_piece.length != r.start
|
||||
|| m_intermediate_piece.piece != r.piece)
|
||||
{
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is the first part of a partial request
|
||||
if (r.start != m_requests.front().start
|
||||
|| r.piece != m_requests.front().piece)
|
||||
{
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
m_intermediate_piece.piece = r.piece;
|
||||
m_intermediate_piece.start = r.start;
|
||||
m_intermediate_piece.length = 0;
|
||||
}
|
||||
|
||||
m_piece.reserve(info.piece_length());
|
||||
std::copy(http_body.begin, http_body.end, back_inserter(m_piece));
|
||||
m_intermediate_piece.length += r.length;
|
||||
if (m_intermediate_piece.length == m_requests.front().length)
|
||||
{
|
||||
assert(m_requests.front() == m_intermediate_piece);
|
||||
assert(int(m_piece.size()) == m_intermediate_piece.length);
|
||||
m_requests.pop_front();
|
||||
incoming_piece(m_intermediate_piece, &m_piece[0]);
|
||||
m_piece.clear();
|
||||
}
|
||||
else if (m_intermediate_piece.length > m_requests.front().length)
|
||||
{
|
||||
throw std::runtime_error("too large HTTP response body");
|
||||
}
|
||||
|
||||
cut_receive_buffer(http_body.end - recv_buffer.begin, 512*1024+1024);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,15 +459,15 @@ namespace libtorrent
|
|||
p.total_download = statistics().total_payload_download();
|
||||
p.total_upload = statistics().total_payload_upload();
|
||||
|
||||
if (m_ul_bandwidth_quota.given == std::numeric_limits<int>::max())
|
||||
if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf)
|
||||
p.upload_limit = -1;
|
||||
else
|
||||
p.upload_limit = m_ul_bandwidth_quota.given;
|
||||
p.upload_limit = m_bandwidth_limit[upload_channel].throttle();
|
||||
|
||||
if (m_dl_bandwidth_quota.given == std::numeric_limits<int>::max())
|
||||
if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf)
|
||||
p.download_limit = -1;
|
||||
else
|
||||
p.download_limit = m_dl_bandwidth_quota.given;
|
||||
p.download_limit = m_bandwidth_limit[download_channel].throttle();
|
||||
|
||||
p.load_balancing = total_free_upload();
|
||||
|
||||
|
|
Loading…
Reference in New Issue