diff --git a/libtorrent/bindings/python/src/torrent_handle.cpp b/libtorrent/bindings/python/src/torrent_handle.cpp index 622ab06a0..a4f1953e2 100755 --- a/libtorrent/bindings/python/src/torrent_handle.cpp +++ b/libtorrent/bindings/python/src/torrent_handle.cpp @@ -148,6 +148,16 @@ void prioritize_files(torrent_handle& info, object o) } } +list file_priorities(torrent_handle& handle) +{ + list ret; + std::vector priorities = handle.file_priorities(); + + for (std::vector::iterator i = priorities.begin(); i != priorities.end(); ++i) + ret.append(*i); + + return ret; +} void replace_trackers(torrent_handle& info, object trackers) { @@ -294,6 +304,7 @@ void bind_torrent_handle() .def("prioritize_pieces", prioritize_pieces) .def("piece_prioritize", piece_priorities) .def("prioritize_files", prioritize_files) + .def("file_priorities", file_priorities) .def("use_interface", &torrent_handle::use_interface) .def("write_resume_data", _(&torrent_handle::write_resume_data)) .def("save_resume_data", _(&torrent_handle::save_resume_data)) diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp index 9b2c0014f..105dde3f5 100644 --- a/libtorrent/include/libtorrent/alert.hpp +++ b/libtorrent/include/libtorrent/alert.hpp @@ -110,6 +110,8 @@ namespace libtorrent { class TORRENT_EXPORT alert_manager { public: + enum { queue_size_limit_default = 1000 }; + alert_manager(); ~alert_manager(); @@ -124,11 +126,15 @@ namespace libtorrent { void set_alert_mask(int m) { m_alert_mask = m; } + size_t alert_queue_size_limit() const { return m_queue_size_limit; } + size_t set_alert_queue_size_limit(size_t queue_size_limit_); + private: std::queue m_alerts; mutable boost::mutex m_mutex; boost::condition m_condition; int m_alert_mask; + size_t m_queue_size_limit; }; struct TORRENT_EXPORT unhandled_alert : std::exception diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index cc24d6987..aa5d1bae1 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -212,6 +212,7 @@ namespace libtorrent void done_checking(boost::shared_ptr const& t); void set_alert_mask(int m); + size_t set_alert_queue_size_limit(size_t queue_size_limit_); std::auto_ptr pop_alert(); alert const* wait_for_alert(time_duration max_wait); diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index f112253ea..1f837e317 100644 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -331,6 +331,7 @@ namespace libtorrent void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED; #endif void set_alert_mask(int m); + size_t set_alert_queue_size_limit(size_t queue_size_limit_); alert const* wait_for_alert(time_duration max_wait); diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp index 87b3e984a..80680b357 100644 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ b/libtorrent/include/libtorrent/torrent_handle.hpp @@ -291,7 +291,7 @@ namespace libtorrent struct TORRENT_EXPORT partial_piece_info { - enum { max_blocks_per_piece = 256 }; + enum { max_blocks_per_piece = 512 }; int piece_index; int blocks_in_piece; // the number of blocks in the finished state diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp index 3e65d2b08..14c5c4e5c 100755 --- a/libtorrent/src/alert.cpp +++ b/libtorrent/src/alert.cpp @@ -35,8 +35,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/alert.hpp" #include -enum { queue_size_limit = 1000 }; - namespace libtorrent { alert::alert() : m_timestamp(time_now()) {} @@ -45,6 +43,7 @@ namespace libtorrent { alert_manager::alert_manager() : m_alert_mask(alert::error_notification) + , m_queue_size_limit(queue_size_limit_default) {} alert_manager::~alert_manager() @@ -85,7 +84,7 @@ namespace libtorrent { { boost::mutex::scoped_lock lock(m_mutex); - if (m_alerts.size() >= queue_size_limit) return; + if (m_alerts.size() >= m_queue_size_limit) return; m_alerts.push(alert_.clone().release()); m_condition.notify_all(); } @@ -108,5 +107,13 @@ namespace libtorrent { return !m_alerts.empty(); } + size_t alert_manager::set_alert_queue_size_limit(size_t queue_size_limit_) + { + boost::mutex::scoped_lock lock(m_mutex); + + std::swap(m_queue_size_limit, queue_size_limit_); + return queue_size_limit_; + } + } // namespace libtorrent diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index c96b8ba33..dcf0a5bcb 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -2639,7 +2639,7 @@ namespace libtorrent TORRENT_ASSERT(!m_rc4_encrypted || m_RC4_handler.get()); #endif - if (is_seed()) TORRENT_ASSERT(upload_only()); + if (is_seed() && m_initialized) TORRENT_ASSERT(upload_only()); if (!in_handshake()) { diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index 31c60171f..0635a60b5 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -635,20 +635,6 @@ namespace libtorrent TORRENT_ASSERT(j.storage); TORRENT_ASSERT(j.buffer_size <= m_block_size); mutex_t::scoped_lock l(m_queue_mutex); -#ifndef NDEBUG - mutex_t::scoped_lock l2(m_piece_mutex); - if (j.action == disk_io_job::write) - { - cache_t::iterator p - = find_cached_piece(m_pieces, j, l2); - if (p != m_pieces.end()) - { - int block = j.offset / m_block_size; - char const* buffer = p->blocks[block]; - TORRENT_ASSERT(buffer == 0); - } - } -#endif std::list::reverse_iterator i = m_jobs.rbegin(); if (j.action == disk_io_job::read) diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 8ed1cd187..6efe61d94 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -2691,6 +2691,8 @@ namespace libtorrent TORRENT_ASSERT(!m_disk_recv_buffer); TORRENT_ASSERT(disk_buffer_size <= 16 * 1024); + if (disk_buffer_size == 0) return true; + if (disk_buffer_size > 16 * 1024) { disconnect("invalid piece size", 2); @@ -3597,6 +3599,12 @@ namespace libtorrent void peer_connection::connect(int ticket) { +#ifndef NDEBUG + // in case we disconnect here, we need to + // keep the connection alive until the + // exit invariant check is run + boost::intrusive_ptr me(self()); +#endif INVARIANT_CHECK; error_code ec; @@ -3855,7 +3863,7 @@ namespace libtorrent TORRENT_ASSERT(m_disconnect_started); } - if (!m_disconnect_started) + if (!m_disconnect_started && m_initialized) { // none of this matters if we're disconnecting anyway if (t->is_finished()) diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 6aeb5fae0..c8b5d8d99 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -1046,7 +1046,9 @@ namespace libtorrent // be removed from the available piece list. void piece_picker::we_have(int index) { +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS TORRENT_PIECE_PICKER_INVARIANT_CHECK; +#endif TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index < (int)m_piece_map.size()); diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index b0db1d9ef..474f88a24 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -553,6 +553,11 @@ namespace libtorrent m_impl->set_alert_mask(m); } + size_t session::set_alert_queue_size_limit(size_t queue_size_limit_) + { + return m_impl->set_alert_queue_size_limit(queue_size_limit_); + } + #ifndef TORRENT_NO_DEPRECATE void session::set_severity_level(alert::severity_t s) { diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index f414a8e58..eab1b0638 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -2285,6 +2285,12 @@ namespace aux { m_alerts.set_alert_mask(m); } + size_t session_impl::set_alert_queue_size_limit(size_t queue_size_limit_) + { + mutex_t::scoped_lock l(m_mutex); + return m_alerts.set_alert_queue_size_limit(queue_size_limit_); + } + int session_impl::upload_rate_limit() const { mutex_t::scoped_lock l(m_mutex); diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 82ed21ffc..737d1aa17 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -2271,7 +2271,11 @@ namespace libtorrent if (num_read < 0) { if (m_storage->error() +#ifdef TORRENT_WINDOWS + && m_storage->error() != error_code(ERROR_FILE_NOT_FOUND, get_system_category())) +#else && m_storage->error() != error_code(ENOENT, get_posix_category())) +#endif { std::cerr << m_storage->error().message() << std::endl; return -1; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 479459510..f7ec7f5ef 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2816,7 +2816,8 @@ namespace libtorrent pi.writing = (int)i->writing; pi.requested = (int)i->requested; int piece_size = int(torrent_file().piece_size(i->index)); - for (int j = 0; j < pi.blocks_in_piece; ++j) + int num_blocks = (std::min)(pi.blocks_in_piece, int(partial_piece_info::max_blocks_per_piece)); + for (int j = 0; j < num_blocks; ++j) { block_info& bi = pi.blocks[j]; bi.state = i->info[j].state; @@ -3251,6 +3252,9 @@ namespace libtorrent { INVARIANT_CHECK; + TORRENT_ASSERT(is_finished()); + TORRENT_ASSERT(m_state != torrent_status::finished && m_state != torrent_status::seeding); + if (alerts().should_post()) { alerts().post_alert(torrent_finished_alert( @@ -3381,7 +3385,10 @@ namespace libtorrent TORRENT_ASSERT(m_torrent_file->is_valid()); INVARIANT_CHECK; - set_state(torrent_status::downloading); + // we might be finished already, in which case we should + // not switch to downloading mode. + if (m_state != torrent_status::finished) + set_state(torrent_status::downloading); if (m_ses.m_alerts.should_post()) { @@ -3396,12 +3403,12 @@ namespace libtorrent if (m_ses.m_auto_manage_time_scaler > 1) m_ses.m_auto_manage_time_scaler = 1; - if (is_finished()) finished(); + if (is_finished() && m_state != torrent_status::finished) finished(); } else { m_complete_sent = true; - finished(); + if (m_state != torrent_status::finished) finished(); } #ifndef TORRENT_DISABLE_EXTENSIONS @@ -4393,6 +4400,15 @@ namespace libtorrent void torrent::set_state(torrent_status::state_t s) { +#ifndef NDEBUG + if (s == torrent_status::seeding) + TORRENT_ASSERT(is_seed()); + if (s == torrent_status::finished) + TORRENT_ASSERT(is_finished()); + if (s == torrent_status::downloading && m_state == torrent_status::finished) + TORRENT_ASSERT(!is_finished()); +#endif + if (m_state == s) return; m_state = s; if (m_ses.m_alerts.should_post()) diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index 6fb5fa992..603cd1a27 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -219,6 +219,7 @@ namespace libtorrent if (ec) return -1; if (s > 5000000) return -2; v.resize(s); + if (s == 0) return 0; f.seek(0, file::begin, ec); if (ec) return -1; size_type read = f.read(&v[0], s, ec);