diff --git a/include/libtorrent/alert_manager.hpp b/include/libtorrent/alert_manager.hpp index 798e555bb..3cd08175a 100644 --- a/include/libtorrent/alert_manager.hpp +++ b/include/libtorrent/alert_manager.hpp @@ -57,8 +57,8 @@ namespace libtorrent { void post_alert(const alert& alert_); void post_alert_ptr(alert* alert_); bool pending() const; - std::auto_ptr get(); - void get_all(std::deque* alerts); + std::auto_ptr get(int& num_resume); + void get_all(std::deque* alerts, int& num_resume); template bool should_post() const @@ -88,6 +88,8 @@ namespace libtorrent { void set_dispatch_function(boost::function)> const&); + int num_queued_resume() const; + #ifndef TORRENT_DISABLE_EXTENSIONS void add_extension(boost::shared_ptr ext); #endif @@ -102,6 +104,9 @@ namespace libtorrent { size_t m_queue_size_limit; boost::function)> m_dispatch; + // the number of resume data alerts in the alert queue + int m_num_queued_resume; + #ifndef TORRENT_DISABLE_EXTENSIONS typedef std::list > ses_extension_list_t; ses_extension_list_t m_ses_extensions; diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 796e7e125..c53354f8e 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -250,7 +250,7 @@ namespace libtorrent void queue_async_resume_data(boost::shared_ptr const& t); void done_async_resume(); - void async_resume_dispatched(bool all); + void async_resume_dispatched(int num_popped_resume); void init_peer_class_filter(bool unlimited_local); @@ -835,10 +835,6 @@ namespace libtorrent // outstanding int m_num_save_resume; - // the number of resume data job that are complete and are waiting - // to be reaped in the alert queue - int m_num_queued_resume; - // peer connections are put here when disconnected to avoid // race conditions with the disk thread. It's important that // peer connections are destructed from the network thread, diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 4a536d12b..df5cbea57 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -287,8 +287,8 @@ namespace libtorrent // // returns one of: // | no_error = 0 - // | need_full_check = -1 - // | fatal_disk_error = -2 + // | fatal_disk_error = -1 + // | need_full_check = -2 // | file_exist = -4 virtual int move_storage(std::string const& save_path, int flags , storage_error& ec) = 0; diff --git a/src/alert_manager.cpp b/src/alert_manager.cpp index b0b108dc2..2915aaa42 100644 --- a/src/alert_manager.cpp +++ b/src/alert_manager.cpp @@ -44,6 +44,7 @@ namespace libtorrent alert_manager::alert_manager(int queue_limit, boost::uint32_t alert_mask) : m_alert_mask(alert_mask) , m_queue_size_limit(queue_limit) + , m_num_queued_resume(0) {} alert_manager::~alert_manager() @@ -59,6 +60,12 @@ namespace libtorrent } } + int alert_manager::num_queued_resume() const + { + mutex::scoped_lock lock(m_mutex); + return m_num_queued_resume; + } + alert const* alert_manager::wait_for_alert(time_duration max_wait) { mutex::scoped_lock lock(m_mutex); @@ -137,6 +144,11 @@ namespace libtorrent void alert_manager::post_impl(std::auto_ptr& alert_ , mutex::scoped_lock& /* l */) { + + if (alert_cast(alert_.get()) + || alert_cast(alert_.get())) + ++m_num_queued_resume; + if (m_dispatch) { TORRENT_ASSERT(m_alerts.empty()); @@ -159,21 +171,37 @@ namespace libtorrent } #endif - std::auto_ptr alert_manager::get() + std::auto_ptr alert_manager::get(int& num_resume) { mutex::scoped_lock lock(m_mutex); if (m_alerts.empty()) return std::auto_ptr(0); + TORRENT_ASSERT(m_num_queued_resume <= int(m_alerts.size())); + alert* result = m_alerts.front(); m_alerts.pop_front(); + + if (alert_cast(result) + || alert_cast(result)) + { + --m_num_queued_resume; + num_resume = 1; + } + else + { + num_resume = 0; + } return std::auto_ptr(result); } - void alert_manager::get_all(std::deque* alerts) + void alert_manager::get_all(std::deque* alerts, int& num_resume) { mutex::scoped_lock lock(m_mutex); + TORRENT_ASSERT(m_num_queued_resume <= int(m_alerts.size())); + num_resume = m_num_queued_resume; + m_num_queued_resume = 0; if (m_alerts.empty()) return; m_alerts.swap(*alerts); } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 4097f1bbc..3a0e49f3c 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -451,7 +451,6 @@ namespace aux { #endif , m_tracker_manager(*this) , m_num_save_resume(0) - , m_num_queued_resume(0) , m_work(io_service::work(m_io_service)) , m_max_queue_pos(-1) , m_key(0) @@ -1118,7 +1117,7 @@ namespace aux { int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit); - if (m_num_save_resume + m_num_queued_resume >= loaded_limit + if (m_num_save_resume + m_alerts.num_queued_resume() >= loaded_limit && m_user_load_torrent && loaded_limit > 0) { @@ -1142,28 +1141,19 @@ namespace aux { { TORRENT_ASSERT(m_num_save_resume > 0); --m_num_save_resume; - ++m_num_queued_resume; } // this is called when one or all save resume alerts are // popped off the alert queue - void session_impl::async_resume_dispatched(bool all) + void session_impl::async_resume_dispatched(int num_popped_resume) { INVARIANT_CHECK; - if (all) - { - m_num_queued_resume = 0; - } - else - { - TORRENT_ASSERT(m_num_queued_resume > 0); - --m_num_queued_resume; - } + int num_queued_resume = m_alerts.num_queued_resume(); int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit); while (!m_save_resume_queue.empty() - && (m_num_save_resume + m_num_queued_resume < loaded_limit + && (m_num_save_resume + num_queued_resume < loaded_limit || loaded_limit == 0)) { boost::shared_ptr t = m_save_resume_queue.front(); @@ -7446,14 +7436,14 @@ retry: // not the network thread std::auto_ptr session_impl::pop_alert() { - std::auto_ptr ret = m_alerts.get(); - if (alert_cast(ret.get()) - || alert_cast(ret.get())) + int num_resume = 0; + std::auto_ptr ret = m_alerts.get(num_resume); + if (num_resume > 0) { // we can only issue more resume data jobs from // the network thread m_io_service.post(boost::bind(&session_impl::async_resume_dispatched - , this, false)); + , this, num_resume)); } return ret; } @@ -7462,11 +7452,12 @@ retry: // not the network thread void session_impl::pop_alerts(std::deque* alerts) { - m_alerts.get_all(alerts); + int num_resume = 0; + m_alerts.get_all(alerts, num_resume); // we can only issue more resume data jobs from // the network thread m_io_service.post(boost::bind(&session_impl::async_resume_dispatched - , this, true)); + , this, num_resume)); } alert const* session_impl::wait_for_alert(time_duration max_wait) diff --git a/src/torrent.cpp b/src/torrent.cpp index 49e0bb6ce..80699aa31 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2422,7 +2422,7 @@ namespace libtorrent dec_refcount("force_recheck"); state_updated(); - if (j->ret < 0) + if (j->ret == piece_manager::fatal_disk_error) { handle_disk_error(j); return; diff --git a/test/test_priority.cpp b/test/test_priority.cpp index 97432abe6..3e6c74afa 100644 --- a/test/test_priority.cpp +++ b/test/test_priority.cpp @@ -245,8 +245,12 @@ void test_transfer(settings_pack const& sett) test_sleep(100); } - TEST_CHECK(st2.state != torrent_status::checking_files); - if (st2.state != torrent_status::checking_files) std::cerr << "recheck complete" << std::endl; + TEST_EQUAL(st2.state, torrent_status::finished); + + if (st2.state != torrent_status::finished) + return; + + std::cerr << "recheck complete" << std::endl; priorities2 = tor2.piece_priorities(); std::copy(priorities2.begin(), priorities2.end(), std::ostream_iterator(std::cerr, ", ")); @@ -291,6 +295,8 @@ void test_transfer(settings_pack const& sett) } TEST_CHECK(resume_data.size()); + fprintf(stderr, "%s\n", resume_data.data()); + ses2.remove_torrent(tor2); std::cerr << "removed" << std::endl;