forked from premiere/premiere-libtorrent
solved issue with pausing checking torrents. Introduced a new state, checkin_resume_data, which a torrent is in while waiting for the disk io thread to verify the resume data, but before it has been determined wheter it should be queued for checking or not
This commit is contained in:
parent
78abf8a340
commit
723aba6c24
|
@ -1,4 +1,9 @@
|
|||
|
||||
* torrents that are checking can now be paused, which will
|
||||
pause the checking
|
||||
* introduced another torrent state, checking_resume_data, which
|
||||
the torrent is in when it's first added, and is comparing
|
||||
the files on disk with the resume data
|
||||
* DHT bandwidth usage optimizations
|
||||
* rate limited DHT send socket
|
||||
* tracker connections are now also subject to IP filtering
|
||||
|
|
|
@ -283,7 +283,8 @@ def main():
|
|||
|
||||
if s.state != lt.torrent_status.seeding:
|
||||
state_str = ['queued', 'checking', 'downloading metadata', \
|
||||
'downloading', 'finished', 'seeding', 'allocating']
|
||||
'downloading', 'finished', 'seeding', \
|
||||
'allocating', 'checking fastresume']
|
||||
out += state_str[s.state] + ' '
|
||||
|
||||
out += '%5.4f%% ' % (s.progress*100)
|
||||
|
|
|
@ -2376,7 +2376,8 @@ It contains the following fields::
|
|||
downloading,
|
||||
finished,
|
||||
seeding,
|
||||
allocating
|
||||
allocating,
|
||||
checking_resume_data
|
||||
};
|
||||
|
||||
state_t state;
|
||||
|
@ -2453,6 +2454,11 @@ It contains the following fields::
|
|||
torrent's current task. It may be checking files or downloading. The torrent's
|
||||
current task is in the ``state`` member, it will be one of the following:
|
||||
|
||||
+--------------------------+----------------------------------------------------------+
|
||||
|``checking_resume_data`` |The torrent is currently checking the fastresume data and |
|
||||
| |comparing it to the files on disk. This is typically |
|
||||
| |completed in a fraction of a second, but if you add a |
|
||||
| |large number of torrents at once, they will queue up. |
|
||||
+--------------------------+----------------------------------------------------------+
|
||||
|``queued_for_checking`` |The torrent is in the queue for being checked. But there |
|
||||
| |currently is another torrent that are being checked. |
|
||||
|
|
|
@ -667,7 +667,7 @@ void handle_alert(libtorrent::session& ses, libtorrent::alert* a
|
|||
|
||||
static char const* state_str[] =
|
||||
{"checking (q)", "checking", "dl metadata"
|
||||
, "downloading", "finished", "seeding", "allocating"};
|
||||
, "downloading", "finished", "seeding", "allocating", "checking (r)"};
|
||||
|
||||
int main(int ac, char* av[])
|
||||
{
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace libtorrent
|
|||
struct TORRENT_EXPORT torrent_status
|
||||
{
|
||||
torrent_status()
|
||||
: state(queued_for_checking)
|
||||
: state(checking_resume_data)
|
||||
, paused(false)
|
||||
, progress(0.f)
|
||||
, total_download(0)
|
||||
|
@ -130,7 +130,8 @@ namespace libtorrent
|
|||
downloading,
|
||||
finished,
|
||||
seeding,
|
||||
allocating
|
||||
allocating,
|
||||
checking_resume_data
|
||||
};
|
||||
|
||||
state_t state;
|
||||
|
|
|
@ -1875,10 +1875,10 @@ namespace aux {
|
|||
void session_impl::check_torrent(boost::shared_ptr<torrent> const& t)
|
||||
{
|
||||
if (m_abort) return;
|
||||
TORRENT_ASSERT(!t->is_paused() || t->is_auto_managed());
|
||||
TORRENT_ASSERT(t->state() == torrent_status::checking_files
|
||||
|| t->state() == torrent_status::queued_for_checking);
|
||||
TORRENT_ASSERT(t->should_check_files());
|
||||
TORRENT_ASSERT(t->state() != torrent_status::checking_files);
|
||||
if (m_queued_for_checking.empty()) t->start_checking();
|
||||
else t->set_state(torrent_status::queued_for_checking);
|
||||
TORRENT_ASSERT(std::find(m_queued_for_checking.begin()
|
||||
, m_queued_for_checking.end(), t) == m_queued_for_checking.end());
|
||||
m_queued_for_checking.push_back(t);
|
||||
|
@ -1900,17 +1900,21 @@ namespace aux {
|
|||
|
||||
void session_impl::done_checking(boost::shared_ptr<torrent> const& t)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_queued_for_checking.empty()) return;
|
||||
check_queue_t::iterator next_check = m_queued_for_checking.begin();
|
||||
check_queue_t::iterator done = m_queued_for_checking.end();
|
||||
for (check_queue_t::iterator i = m_queued_for_checking.begin()
|
||||
, end(m_queued_for_checking.end()); i != end; ++i)
|
||||
{
|
||||
TORRENT_ASSERT(*i == t || (*i)->should_check_files());
|
||||
if (*i == t) done = i;
|
||||
if (next_check == done || (*next_check)->queue_position() > (*i)->queue_position())
|
||||
next_check = i;
|
||||
}
|
||||
if (next_check != done) (*next_check)->start_checking();
|
||||
// only start a new one if we removed the one that is checking
|
||||
if (next_check != done && t->state() == torrent_status::checking_files) (*next_check)->start_checking();
|
||||
m_queued_for_checking.erase(done);
|
||||
}
|
||||
|
||||
|
@ -2631,6 +2635,13 @@ namespace aux {
|
|||
#ifndef NDEBUG
|
||||
void session_impl::check_invariant() const
|
||||
{
|
||||
int num_checking = std::count_if(m_queued_for_checking.begin()
|
||||
, m_queued_for_checking.end(), boost::bind(&torrent::state, _1)
|
||||
== torrent_status::checking_files);
|
||||
|
||||
// the queue is either empty, or it has exactly one checking torrent in it
|
||||
TORRENT_ASSERT(m_queued_for_checking.empty() || num_checking == 1);
|
||||
|
||||
std::set<int> unique;
|
||||
int total_downloaders = 0;
|
||||
for (torrent_map::const_iterator i = m_torrents.begin()
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace libtorrent
|
|||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_storage_mode(storage_mode)
|
||||
, m_state(torrent_status::queued_for_checking)
|
||||
, m_state(torrent_status::checking_resume_data)
|
||||
, m_settings(ses.settings())
|
||||
, m_storage_constructor(sc)
|
||||
, m_progress(0.f)
|
||||
|
@ -250,7 +250,7 @@ namespace libtorrent
|
|||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_storage_mode(storage_mode)
|
||||
, m_state(torrent_status::queued_for_checking)
|
||||
, m_state(torrent_status::checking_resume_data)
|
||||
, m_settings(ses.settings())
|
||||
, m_storage_constructor(sc)
|
||||
, m_progress(0.f)
|
||||
|
@ -472,7 +472,7 @@ namespace libtorrent
|
|||
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
|
||||
, m_web_seeds.begin()));
|
||||
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
set_state(torrent_status::checking_resume_data);
|
||||
|
||||
if (m_resume_entry.type() == lazy_entry::dict_t)
|
||||
{
|
||||
|
@ -552,6 +552,7 @@ namespace libtorrent
|
|||
}
|
||||
m_error = j.str;
|
||||
pause();
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
|
||||
std::vector<char>().swap(m_resume_data);
|
||||
lazy_entry().swap(m_resume_entry);
|
||||
|
@ -680,7 +681,8 @@ namespace libtorrent
|
|||
{
|
||||
// either the fastresume data was rejected or there are
|
||||
// some files
|
||||
if (!is_torrent_paused() || is_auto_managed())
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
if (should_check_files())
|
||||
m_ses.check_torrent(shared_from_this());
|
||||
}
|
||||
|
||||
|
@ -690,10 +692,21 @@ namespace libtorrent
|
|||
|
||||
void torrent::force_recheck()
|
||||
{
|
||||
if (m_state == torrent_status::checking_files
|
||||
|| m_state == torrent_status::queued_for_checking)
|
||||
// if the torrent is already queued to check its files
|
||||
// don't do anything
|
||||
if (should_check_files()
|
||||
|| m_state == torrent_status::checking_resume_data)
|
||||
return;
|
||||
|
||||
if ((is_paused() && !m_auto_managed))
|
||||
{
|
||||
// set the queued for checking state, so that it's
|
||||
// checked as soon as it's resumed or made auto managed
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
return;
|
||||
}
|
||||
if (!m_error.empty()) m_error.clear();
|
||||
|
||||
disconnect_all();
|
||||
|
||||
m_owning_storage->async_release_files();
|
||||
|
@ -706,7 +719,7 @@ namespace libtorrent
|
|||
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
||||
// assume that we don't have anything
|
||||
m_files_checked = false;
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
set_state(torrent_status::checking_resume_data);
|
||||
|
||||
if (m_auto_managed)
|
||||
set_queue_position((std::numeric_limits<int>::max)());
|
||||
|
@ -744,6 +757,7 @@ namespace libtorrent
|
|||
|
||||
void torrent::start_checking()
|
||||
{
|
||||
TORRENT_ASSERT(should_check_files());
|
||||
set_state(torrent_status::checking_files);
|
||||
|
||||
m_storage->async_check_files(bind(
|
||||
|
@ -773,7 +787,11 @@ namespace libtorrent
|
|||
}
|
||||
m_error = j.str;
|
||||
pause();
|
||||
if (!m_abort) m_ses.done_checking(shared_from_this());
|
||||
if (!m_abort)
|
||||
{
|
||||
m_ses.done_checking(shared_from_this());
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1636,7 +1654,10 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
if (m_state == torrent_status::checking_files)
|
||||
{
|
||||
m_ses.done_checking(shared_from_this());
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
}
|
||||
|
||||
m_owning_storage = 0;
|
||||
m_host_resolver.cancel();
|
||||
|
@ -3065,7 +3086,8 @@ namespace libtorrent
|
|||
m_has_incoming = true;
|
||||
|
||||
if ((m_state == torrent_status::queued_for_checking
|
||||
|| m_state == torrent_status::checking_files)
|
||||
|| m_state == torrent_status::checking_files
|
||||
|| m_state == torrent_status::checking_resume_data)
|
||||
&& valid_metadata())
|
||||
{
|
||||
p->disconnect("torrent is not ready to accept peers");
|
||||
|
@ -3133,8 +3155,9 @@ namespace libtorrent
|
|||
{
|
||||
return int(m_connections.size()) < m_max_connections
|
||||
&& !is_paused()
|
||||
&& m_state != torrent_status::checking_files
|
||||
&& (m_state != torrent_status::queued_for_checking
|
||||
&& ((m_state != torrent_status::checking_files
|
||||
&& m_state != torrent_status::checking_resume_data
|
||||
&& m_state != torrent_status::queued_for_checking)
|
||||
|| !valid_metadata())
|
||||
&& m_policy.num_connect_candidates() > 0
|
||||
&& !m_abort;
|
||||
|
@ -3600,6 +3623,9 @@ namespace libtorrent
|
|||
|
||||
if (is_paused()) TORRENT_ASSERT(num_peers() == 0);
|
||||
|
||||
if (!should_check_files())
|
||||
TORRENT_ASSERT(m_state != torrent_status::checking_files);
|
||||
|
||||
if (!m_ses.m_queued_for_checking.empty())
|
||||
{
|
||||
// if there are torrents waiting to be checked
|
||||
|
@ -3891,9 +3917,12 @@ namespace libtorrent
|
|||
void torrent::clear_error()
|
||||
{
|
||||
if (m_error.empty()) return;
|
||||
bool checking_files = should_check_files();
|
||||
if (m_ses.m_auto_manage_time_scaler > 2)
|
||||
m_ses.m_auto_manage_time_scaler = 2;
|
||||
m_error.clear();
|
||||
if (!checking_files && should_check_files())
|
||||
m_ses.check_torrent(shared_from_this());
|
||||
}
|
||||
|
||||
void torrent::auto_managed(bool a)
|
||||
|
@ -3914,6 +3943,7 @@ namespace libtorrent
|
|||
// stop checking
|
||||
m_storage->abort_disk_io();
|
||||
m_ses.done_checking(shared_from_this());
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3994,7 +4024,8 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_storage);
|
||||
if (m_state == torrent_status::queued_for_checking
|
||||
|| m_state == torrent_status::checking_files)
|
||||
|| m_state == torrent_status::checking_files
|
||||
|| m_state == torrent_status::checking_resume_data)
|
||||
{
|
||||
if (alerts().should_post<save_resume_data_failed_alert>())
|
||||
{
|
||||
|
@ -4011,7 +4042,8 @@ namespace libtorrent
|
|||
{
|
||||
return (m_state == torrent_status::checking_files
|
||||
|| m_state == torrent_status::queued_for_checking)
|
||||
&& (!is_paused() || m_auto_managed);
|
||||
&& (!is_paused() || m_auto_managed)
|
||||
&& m_error.empty();
|
||||
}
|
||||
|
||||
bool torrent::is_paused() const
|
||||
|
@ -4033,6 +4065,7 @@ namespace libtorrent
|
|||
// stop checking
|
||||
m_storage->abort_disk_io();
|
||||
m_ses.done_checking(shared_from_this());
|
||||
set_state(torrent_status::queued_for_checking);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue