diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp index d32d250fc..6ec2e465e 100755 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -74,9 +74,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_type.hpp" #include "libtorrent/intrusive_ptr_base.hpp" -// TODO: each time a block is 'taken over' -// from another peer. That peer must be given -// a chance to become not-interested. namespace libtorrent { @@ -701,6 +698,9 @@ namespace libtorrent // a timestamp when the remote download rate // was last updated ptime m_remote_dl_update; + // the number of bytes send to the disk-io + // thread that hasn't yet been completely written. + int m_outstanding_writing_bytes; #ifndef NDEBUG public: diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 783492227..45aa3957f 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -108,6 +108,7 @@ namespace libtorrent , unchoke_interval(20) , num_want(200) , initial_picker_threshold(4) + , max_outstanding_disk_bytes_per_connection(128 * 1024) #ifndef TORRENT_DISABLE_DHT , use_dht_as_fallback(true) #endif @@ -250,7 +251,15 @@ namespace libtorrent // while we have fewer pieces than this, pick // random pieces instead of rarest first. int initial_picker_threshold; - + + // the maximum number of bytes a connection may have + // pending in the disk write queue before its download + // rate is being throttled. This prevents fast downloads + // to slow medias to allocate more and more memory + // indefinitely. This should be set to at least 32 kB + // to not completely disrupt normal downloads. + int max_outstanding_disk_bytes_per_connection; + #ifndef TORRENT_DISABLE_DHT // while this is true, the dht will note be used unless the // tracker is online diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 397c7b16f..d06fe5db3 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -116,6 +116,7 @@ namespace libtorrent , m_remote_bytes_dled(0) , m_remote_dl_rate(0) , m_remote_dl_update(time_now()) + , m_outstanding_writing_bytes(0) #ifndef NDEBUG , m_in_constructor(true) #endif @@ -189,6 +190,7 @@ namespace libtorrent , m_remote_bytes_dled(0) , m_remote_dl_rate(0) , m_remote_dl_update(time_now()) + , m_outstanding_writing_bytes(0) #ifndef NDEBUG , m_in_constructor(true) #endif @@ -1150,6 +1152,7 @@ namespace libtorrent fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete , self(), _1, _2, p, t)); + m_outstanding_writing_bytes += p.length; picker.mark_as_writing(block_finished, peer_info_struct()); } @@ -1158,6 +1161,12 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + m_outstanding_writing_bytes -= p.length; + assert(m_outstanding_writing_bytes >= 0); + // in case the outstanding bytes just dropped down + // to allow to receive more data + setup_receive(); + if (ret == -1 || !t) { if (!t) @@ -2338,7 +2347,9 @@ namespace libtorrent || !m_send_buffer[(m_current_send_buffer + 1) & 1].empty()) && (m_bandwidth_limit[upload_channel].quota_left() > 0 || m_ignore_bandwidth_limits) - && !m_connecting; + && !m_connecting + && m_outstanding_writing_bytes < + m_ses.settings().max_outstanding_disk_bytes_per_connection; } bool peer_connection::can_read() const