diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 4e2f6d391..6de4cfbf1 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -506,9 +506,11 @@ void print_peer_info(std::string& out, std::vector const& , (i->flags & peer_info::on_parole)?'p':'.' , (i->flags & peer_info::optimistic_unchoke)?'O':'.' , (i->read_state == peer_info::bw_limit)?'r': - (i->read_state == peer_info::bw_network)?'R':'.' + (i->read_state == peer_info::bw_network)?'R': + (i->read_state == peer_info::bw_disk)?'D':'.' , (i->write_state == peer_info::bw_limit)?'w': - (i->write_state == peer_info::bw_network)?'W':'.' + (i->write_state == peer_info::bw_network)?'W': + (i->write_state == peer_info::bw_disk)?'D':'.' , (i->flags & peer_info::snubbed)?'S':'.' , (i->flags & peer_info::upload_only)?'U':'D' , (i->flags & peer_info::endgame_mode)?'-':'.' diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 9bc93bdc2..54363cfaf 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -423,6 +423,9 @@ namespace libtorrent , int source_type, address const& source); address const& external_address() const { return m_external_address; } + bool can_write_to_disk() const + { return m_disk_thread.can_write(); } + // used when posting synchronous function // calls to session_impl and torrent objects mutable libtorrent::mutex mut; diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 7d9233a97..62ed18e4b 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -303,6 +303,7 @@ namespace libtorrent // this is used to slow down the download global download // speed when the queue buffer size is too big. size_type queue_buffer_size() const; + bool can_write() const; void get_cache_info(sha1_hash const& ih , std::vector& ret) const; diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index a2d387a2a..f7df73938 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -215,8 +215,6 @@ namespace libtorrent void async_check_files(boost::function const& handler); - int queued_bytes() const; - void async_rename_file(int index, std::string const& name , boost::function const& handler); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 65823d8f3..9da20b44f 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -321,6 +321,7 @@ namespace libtorrent , m_queue_buffer_size(0) , m_last_file_check(time_now_hires()) , m_physical_ram(0) + , m_exceeded_write_queue(false) , m_ios(ios) , m_queue_callback(queue_callback) , m_work(io_service::work(m_ios)) @@ -356,6 +357,12 @@ namespace libtorrent m_jobs.clear(); } + bool disk_io_thread::can_write() const + { + mutex::scoped_lock l(m_queue_mutex); + return !m_exceeded_write_queue; + } + void disk_io_thread::get_cache_info(sha1_hash const& ih, std::vector& ret) const { mutex::scoped_lock l(m_piece_mutex); @@ -1623,14 +1630,15 @@ namespace libtorrent if (m_exceeded_write_queue) { int low_watermark = m_settings.max_queued_disk_bytes_low_watermark == 0 - ? m_settings.max_queued_disk_bytes * 3 / 4 + ? m_settings.max_queued_disk_bytes / 2 : m_settings.max_queued_disk_bytes_low_watermark; if (low_watermark >= m_settings.max_queued_disk_bytes) - low_watermark = m_settings.max_queued_disk_bytes * 3 / 4; + low_watermark = m_settings.max_queued_disk_bytes / 2; if (m_queue_buffer_size < low_watermark - || m_settings.max_queued_disk_bytes > 0) + || m_settings.max_queued_disk_bytes == 0) { + m_exceeded_write_queue = false; // we just dropped below the high watermark of number of bytes // queued for writing to the disk. Notify the session so that it // can trigger all the connections waiting for this event @@ -1734,7 +1742,10 @@ namespace libtorrent , operation_has_buffer(j) ? j.buffer : 0); if (post && m_queue_callback) + { + TORRENT_ASSERT(m_exceeded_write_queue == false); m_ios.post(m_queue_callback); + } flush_expired_pieces(); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 208070506..4afd77a1b 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -2410,7 +2410,7 @@ namespace libtorrent TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); m_download_queue.erase(b); - if (t->filesystem().queued_bytes() >= m_ses.settings().max_queued_disk_bytes + if (!m_ses.can_write_to_disk() && m_ses.settings().max_queued_disk_bytes && t->alerts().should_post() && (now - m_ses.m_last_disk_performance_warning) > seconds(10)) @@ -5064,8 +5064,7 @@ namespace libtorrent if (!bw_limit) return false; bool disk = m_ses.settings().max_queued_disk_bytes == 0 - || !t || t->get_storage() == 0 - || t->filesystem().queued_bytes() < m_ses.settings().max_queued_disk_bytes + || m_ses.can_write_to_disk() // don't block this peer because of disk saturation // if we're not downloading any pieces from it || m_outstanding_bytes == 0; diff --git a/src/storage.cpp b/src/storage.cpp index 337a6ac9e..84d2c25fa 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1626,11 +1626,6 @@ ret: #endif } - int piece_manager::queued_bytes() const - { - return m_io_thread.queue_buffer_size(); - } - void piece_manager::async_write( peer_request const& r , disk_buffer_holder& buffer