fixed issue with queued resume data saving, and fixed regression in recent disk error check changes

This commit is contained in:
Arvid Norberg 2014-07-21 03:03:59 +00:00
parent c519968aa4
commit 79a2744fa8
7 changed files with 60 additions and 34 deletions

View File

@ -57,8 +57,8 @@ namespace libtorrent {
void post_alert(const alert& alert_); void post_alert(const alert& alert_);
void post_alert_ptr(alert* alert_); void post_alert_ptr(alert* alert_);
bool pending() const; bool pending() const;
std::auto_ptr<alert> get(); std::auto_ptr<alert> get(int& num_resume);
void get_all(std::deque<alert*>* alerts); void get_all(std::deque<alert*>* alerts, int& num_resume);
template <class T> template <class T>
bool should_post() const bool should_post() const
@ -88,6 +88,8 @@ namespace libtorrent {
void set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const&); void set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const&);
int num_queued_resume() const;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<plugin> ext); void add_extension(boost::shared_ptr<plugin> ext);
#endif #endif
@ -102,6 +104,9 @@ namespace libtorrent {
size_t m_queue_size_limit; size_t m_queue_size_limit;
boost::function<void(std::auto_ptr<alert>)> m_dispatch; boost::function<void(std::auto_ptr<alert>)> m_dispatch;
// the number of resume data alerts in the alert queue
int m_num_queued_resume;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<plugin> > ses_extension_list_t; typedef std::list<boost::shared_ptr<plugin> > ses_extension_list_t;
ses_extension_list_t m_ses_extensions; ses_extension_list_t m_ses_extensions;

View File

@ -250,7 +250,7 @@ namespace libtorrent
void queue_async_resume_data(boost::shared_ptr<torrent> const& t); void queue_async_resume_data(boost::shared_ptr<torrent> const& t);
void done_async_resume(); 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); void init_peer_class_filter(bool unlimited_local);
@ -835,10 +835,6 @@ namespace libtorrent
// outstanding // outstanding
int m_num_save_resume; 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 // peer connections are put here when disconnected to avoid
// race conditions with the disk thread. It's important that // race conditions with the disk thread. It's important that
// peer connections are destructed from the network thread, // peer connections are destructed from the network thread,

View File

@ -287,8 +287,8 @@ namespace libtorrent
// //
// returns one of: // returns one of:
// | no_error = 0 // | no_error = 0
// | need_full_check = -1 // | fatal_disk_error = -1
// | fatal_disk_error = -2 // | need_full_check = -2
// | file_exist = -4 // | file_exist = -4
virtual int move_storage(std::string const& save_path, int flags virtual int move_storage(std::string const& save_path, int flags
, storage_error& ec) = 0; , storage_error& ec) = 0;

View File

@ -44,6 +44,7 @@ namespace libtorrent
alert_manager::alert_manager(int queue_limit, boost::uint32_t alert_mask) alert_manager::alert_manager(int queue_limit, boost::uint32_t alert_mask)
: m_alert_mask(alert_mask) : m_alert_mask(alert_mask)
, m_queue_size_limit(queue_limit) , m_queue_size_limit(queue_limit)
, m_num_queued_resume(0)
{} {}
alert_manager::~alert_manager() 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) alert const* alert_manager::wait_for_alert(time_duration max_wait)
{ {
mutex::scoped_lock lock(m_mutex); mutex::scoped_lock lock(m_mutex);
@ -137,6 +144,11 @@ namespace libtorrent
void alert_manager::post_impl(std::auto_ptr<alert>& alert_ void alert_manager::post_impl(std::auto_ptr<alert>& alert_
, mutex::scoped_lock& /* l */) , mutex::scoped_lock& /* l */)
{ {
if (alert_cast<save_resume_data_failed_alert>(alert_.get())
|| alert_cast<save_resume_data_alert>(alert_.get()))
++m_num_queued_resume;
if (m_dispatch) if (m_dispatch)
{ {
TORRENT_ASSERT(m_alerts.empty()); TORRENT_ASSERT(m_alerts.empty());
@ -159,21 +171,37 @@ namespace libtorrent
} }
#endif #endif
std::auto_ptr<alert> alert_manager::get() std::auto_ptr<alert> alert_manager::get(int& num_resume)
{ {
mutex::scoped_lock lock(m_mutex); mutex::scoped_lock lock(m_mutex);
if (m_alerts.empty()) if (m_alerts.empty())
return std::auto_ptr<alert>(0); return std::auto_ptr<alert>(0);
TORRENT_ASSERT(m_num_queued_resume <= int(m_alerts.size()));
alert* result = m_alerts.front(); alert* result = m_alerts.front();
m_alerts.pop_front(); m_alerts.pop_front();
if (alert_cast<save_resume_data_failed_alert>(result)
|| alert_cast<save_resume_data_alert>(result))
{
--m_num_queued_resume;
num_resume = 1;
}
else
{
num_resume = 0;
}
return std::auto_ptr<alert>(result); return std::auto_ptr<alert>(result);
} }
void alert_manager::get_all(std::deque<alert*>* alerts) void alert_manager::get_all(std::deque<alert*>* alerts, int& num_resume)
{ {
mutex::scoped_lock lock(m_mutex); 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; if (m_alerts.empty()) return;
m_alerts.swap(*alerts); m_alerts.swap(*alerts);
} }

View File

@ -451,7 +451,6 @@ namespace aux {
#endif #endif
, m_tracker_manager(*this) , m_tracker_manager(*this)
, m_num_save_resume(0) , m_num_save_resume(0)
, m_num_queued_resume(0)
, m_work(io_service::work(m_io_service)) , m_work(io_service::work(m_io_service))
, m_max_queue_pos(-1) , m_max_queue_pos(-1)
, m_key(0) , m_key(0)
@ -1118,7 +1117,7 @@ namespace aux {
int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit); 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 && m_user_load_torrent
&& loaded_limit > 0) && loaded_limit > 0)
{ {
@ -1142,28 +1141,19 @@ namespace aux {
{ {
TORRENT_ASSERT(m_num_save_resume > 0); TORRENT_ASSERT(m_num_save_resume > 0);
--m_num_save_resume; --m_num_save_resume;
++m_num_queued_resume;
} }
// this is called when one or all save resume alerts are // this is called when one or all save resume alerts are
// popped off the alert queue // 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; INVARIANT_CHECK;
if (all) int num_queued_resume = m_alerts.num_queued_resume();
{
m_num_queued_resume = 0;
}
else
{
TORRENT_ASSERT(m_num_queued_resume > 0);
--m_num_queued_resume;
}
int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit); int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit);
while (!m_save_resume_queue.empty() 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)) || loaded_limit == 0))
{ {
boost::shared_ptr<torrent> t = m_save_resume_queue.front(); boost::shared_ptr<torrent> t = m_save_resume_queue.front();
@ -7446,14 +7436,14 @@ retry:
// not the network thread // not the network thread
std::auto_ptr<alert> session_impl::pop_alert() std::auto_ptr<alert> session_impl::pop_alert()
{ {
std::auto_ptr<alert> ret = m_alerts.get(); int num_resume = 0;
if (alert_cast<save_resume_data_failed_alert>(ret.get()) std::auto_ptr<alert> ret = m_alerts.get(num_resume);
|| alert_cast<save_resume_data_alert>(ret.get())) if (num_resume > 0)
{ {
// we can only issue more resume data jobs from // we can only issue more resume data jobs from
// the network thread // the network thread
m_io_service.post(boost::bind(&session_impl::async_resume_dispatched m_io_service.post(boost::bind(&session_impl::async_resume_dispatched
, this, false)); , this, num_resume));
} }
return ret; return ret;
} }
@ -7462,11 +7452,12 @@ retry:
// not the network thread // not the network thread
void session_impl::pop_alerts(std::deque<alert*>* alerts) void session_impl::pop_alerts(std::deque<alert*>* 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 // we can only issue more resume data jobs from
// the network thread // the network thread
m_io_service.post(boost::bind(&session_impl::async_resume_dispatched 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) alert const* session_impl::wait_for_alert(time_duration max_wait)

View File

@ -2422,7 +2422,7 @@ namespace libtorrent
dec_refcount("force_recheck"); dec_refcount("force_recheck");
state_updated(); state_updated();
if (j->ret < 0) if (j->ret == piece_manager::fatal_disk_error)
{ {
handle_disk_error(j); handle_disk_error(j);
return; return;

View File

@ -245,8 +245,12 @@ void test_transfer(settings_pack const& sett)
test_sleep(100); test_sleep(100);
} }
TEST_CHECK(st2.state != torrent_status::checking_files); TEST_EQUAL(st2.state, torrent_status::finished);
if (st2.state != torrent_status::checking_files) std::cerr << "recheck complete" << std::endl;
if (st2.state != torrent_status::finished)
return;
std::cerr << "recheck complete" << std::endl;
priorities2 = tor2.piece_priorities(); priorities2 = tor2.piece_priorities();
std::copy(priorities2.begin(), priorities2.end(), std::ostream_iterator<int>(std::cerr, ", ")); std::copy(priorities2.begin(), priorities2.end(), std::ostream_iterator<int>(std::cerr, ", "));
@ -291,6 +295,8 @@ void test_transfer(settings_pack const& sett)
} }
TEST_CHECK(resume_data.size()); TEST_CHECK(resume_data.size());
fprintf(stderr, "%s\n", resume_data.data());
ses2.remove_torrent(tor2); ses2.remove_torrent(tor2);
std::cerr << "removed" << std::endl; std::cerr << "removed" << std::endl;