diff --git a/docs/manual.rst b/docs/manual.rst index 9b9b3af52..ce5ec2642 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -1532,6 +1532,7 @@ Its declaration looks like this:: void resume() const; bool is_paused() const; bool is_seed() const; + void force_recheck() const; void resolve_countries(bool r); bool resolve_countries() const; @@ -1788,6 +1789,20 @@ all potential (not connected) peers. You can use ``is_paused()`` to determine if is currently paused. Torrents may be paused automatically if there is a file error (e.g. disk full) or something similar. See file_error_alert_. +force_recheck() +--------------- + + :: + + void force_recheck() const; + +``force_recheck`` puts the torrent back in a state where it assumes to have no resume data. +All peers will be disconnected and the torrent will stop announcing to the tracker. The torrent +will be added to the checking queue, and will be checked (all the files will be read and +compared to the piece hashes). Once the check is complete, the torrent will start connecting +to peers again, as normal. + + resolve_countries() ------------------- diff --git a/examples/client_test.cpp b/examples/client_test.cpp index bead43561..a6db082be 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -1065,6 +1065,14 @@ int main(int ac, char* av[]) break; } + if (c == 'j') + { + // force recheck all torrents + std::for_each(handles.begin(), handles.end() + , bind(&torrent_handle::force_recheck + , bind(&handles_t::value_type::second, _1))); + } + if (c == 'r') { // force reannounce on all torrents @@ -1205,7 +1213,8 @@ int main(int ac, char* av[]) std::stringstream out; out << "[q] quit [i] toggle peers [d] toggle downloading pieces [p] pause all " - "[u] unpause all [a] toggle piece bar [s] toggle download sequential [f] toggle files\n" + "[u] unpause all [a] toggle piece bar [s] toggle download sequential [f] toggle files " + "[j] force recheck\n" "[1] toggle IP [2] toggle AS [3] toggle timers [4] toggle block progress " "[5] toggle peer rate [6] toggle failures [7] toggle send buffers\n"; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index da33b7ecd..778d4d4aa 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -149,6 +149,7 @@ namespace libtorrent void init(); void on_resume_data_checked(int ret, disk_io_job const& j); + void on_force_recheck(int ret, disk_io_job const& j); void on_piece_checked(int ret, disk_io_job const& j); void files_checked(); void start_checking(); @@ -191,6 +192,7 @@ namespace libtorrent void pause(); void resume(); bool is_paused() const { return m_paused; } + void force_recheck(); void save_resume_data(); bool is_auto_managed() const { return m_auto_managed; } @@ -906,9 +908,10 @@ namespace libtorrent // connection to this torrent bool m_has_incoming:1; -#ifndef NDEBUG + // this is set to true when the files are checked + // before the files are checked, we don't try to + // connect to peers bool m_files_checked:1; -#endif }; inline ptime torrent::next_announce() const diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 9f21b099d..636e842f0 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -345,6 +345,7 @@ namespace libtorrent bool is_paused() const; void pause() const; void resume() const; + void force_recheck() const; void save_resume_data() const; bool is_auto_managed() const; diff --git a/src/torrent.cpp b/src/torrent.cpp index 8344a1fec..e5a5d721b 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -201,11 +201,9 @@ namespace libtorrent , m_got_tracker_response(false) , m_connections_initialized(true) , m_has_incoming(false) + , m_files_checked(false) { if (resume_data) m_resume_data = *resume_data; -#ifndef NDEBUG - m_files_checked = false; -#endif } torrent::torrent( @@ -308,10 +306,10 @@ namespace libtorrent if (m_ses.m_listen_sockets.empty()) return false; if (!m_ses.m_dht) return false; + if (!m_files_checked) return false; // don't announce private torrents if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; - if (m_trackers.empty()) return true; return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback; @@ -619,6 +617,51 @@ namespace libtorrent } } + void torrent::force_recheck() + { + disconnect_all(); + + m_owning_storage->async_release_files(); + m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file + , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor + , m_storage_mode); + m_storage = m_owning_storage.get(); + m_picker.reset(new piece_picker); + m_picker->init(m_torrent_file->piece_length() / m_block_size + , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); + // assume that we don't have anything + m_files_checked = false; + m_state = torrent_status::queued_for_checking; + + m_resume_data = entry(); + m_storage->async_check_fastresume(&m_resume_data + , bind(&torrent::on_force_recheck + , shared_from_this(), _1, _2)); + } + + void torrent::on_force_recheck(int ret, disk_io_job const& j) + { + session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + + if (ret == piece_manager::fatal_disk_error) + { + if (m_ses.m_alerts.should_post(alert::fatal)) + { + m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str)); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << time_now_string() << ": fatal disk error [" + " error: " << j.str << + " torrent: " << torrent_file().name() << + " ]\n"; +#endif + } + m_error = j.str; + pause(); + return; + } + m_ses.check_torrent(shared_from_this()); + } + void torrent::start_checking() { m_state = torrent_status::checking_files; @@ -770,6 +813,7 @@ namespace libtorrent // INVARIANT_CHECK; if (m_trackers.empty()) return false; + if (!m_files_checked) return false; if (m_just_paused) { @@ -3148,9 +3192,7 @@ namespace libtorrent , "torrent finished checking")); } -#ifndef NDEBUG m_files_checked = true; -#endif } alert_manager& torrent::alerts() const diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 257a05563..fe70c4b92 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -265,6 +265,12 @@ namespace libtorrent TORRENT_FORWARD(save_resume_data()); } + void torrent_handle::force_recheck() const + { + INVARIANT_CHECK; + TORRENT_FORWARD(force_recheck()); + } + void torrent_handle::resume() const { INVARIANT_CHECK;