diff --git a/libtorrent/bindings/python/src/alert.cpp b/libtorrent/bindings/python/src/alert.cpp index 85a4fae2f..01b73ac61 100755 --- a/libtorrent/bindings/python/src/alert.cpp +++ b/libtorrent/bindings/python/src/alert.cpp @@ -274,5 +274,11 @@ void bind_alert() class_, noncopyable>( "torrent_resumed_alert", no_init - ); + ); + + class_, noncopyable>( + "state_changed_alert", no_init + ) + .def_readonly("state", &state_changed_alert::state) + ; } diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp index 1fc8116ff..5d26a66c2 100644 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ b/libtorrent/include/libtorrent/alert_types.hpp @@ -68,6 +68,21 @@ namespace libtorrent std::string name; }; + struct TORRENT_EXPORT state_changed_alert: torrent_alert + { + state_changed_alert(torrent_handle const& h + , torrent_status::state_t const& state_ + , std::string const& msg) + : torrent_alert(h, alert::info, msg) + , state(state_) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new state_changed_alert(*this)); } + + torrent_status::state_t state; + }; + struct TORRENT_EXPORT tracker_alert: torrent_alert { tracker_alert(torrent_handle const& h diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index cf834e833..b1c2cc541 100644 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -167,6 +167,7 @@ namespace libtorrent bool is_aborted() const { return m_abort; } torrent_status::state_t state() const { return m_state; } + void set_state(torrent_status::state_t s); session_settings const& settings() const; @@ -194,6 +195,7 @@ namespace libtorrent void ip_filter_updated() { m_policy.ip_filter_updated(); } + void set_error(std::string const& msg) { m_error = msg; } bool has_error() const { return !m_error.empty(); } void pause(); void resume(); diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index 183c60e97..5158796b6 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -271,12 +271,16 @@ void http_connection::on_resolve(error_code const& e std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints) , boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1)); + // The following statement causes msvc to crash (ICE). Since it's not + // necessary in the vast majority of cases, just ignore the endpoint + // order for windows +#if !defined _MSC_VER || _MSC_VER > 1310 // sort the endpoints so that the ones with the same IP version as our // bound listen socket are first. So that when contacting a tracker, // we'll talk to it from the same IP that we're listening on - m_endpoints.sort( - (bind(&address::is_v4, bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4()) - > (bind(&address::is_v4, bind(&tcp::endpoint::address, _2)) == m_bind_addr.is_v4())); + std::partition(m_endpoints.begin(), m_endpoints.end() + , boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4()); +#endif queue_connect(); } diff --git a/libtorrent/src/lazy_bdecode.cpp b/libtorrent/src/lazy_bdecode.cpp index ffb15f87a..5c1e37419 100644 --- a/libtorrent/src/lazy_bdecode.cpp +++ b/libtorrent/src/lazy_bdecode.cpp @@ -35,6 +35,16 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +namespace +{ + enum + { + lazy_entry_grow_factor = 3, + lazy_entry_dict_init = 30, + lazy_entry_list_init = 50 + }; +} + namespace libtorrent { int fail_bdecode() { return -1; } @@ -176,14 +186,14 @@ namespace libtorrent TORRENT_ASSERT(m_size <= m_capacity); if (m_capacity == 0) { - int capacity = 10; + int capacity = lazy_entry_dict_init; m_data.dict = new (std::nothrow) std::pair[capacity]; if (m_data.dict == 0) return 0; m_capacity = capacity; } else if (m_size == m_capacity) { - int capacity = m_capacity * 2; + int capacity = m_capacity * lazy_entry_grow_factor; std::pair* tmp = new (std::nothrow) std::pair[capacity]; if (tmp == 0) return 0; std::memcpy(tmp, m_data.dict, sizeof(std::pair) * m_size); @@ -289,14 +299,14 @@ namespace libtorrent TORRENT_ASSERT(m_size <= m_capacity); if (m_capacity == 0) { - int capacity = 10; + int capacity = lazy_entry_list_init; m_data.list = new (std::nothrow) lazy_entry[capacity]; if (m_data.list == 0) return 0; m_capacity = capacity; } else if (m_size == m_capacity) { - int capacity = m_capacity * 2; + int capacity = m_capacity * lazy_entry_grow_factor; lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity]; if (tmp == 0) return 0; std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index da82bbf15..8f69665fa 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -2847,6 +2847,7 @@ namespace libtorrent { t->alerts().post_alert(file_error_alert(j.error_file, t->get_handle(), j.str)); } + t->set_error(j.str); t->pause(); return; } diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 048b9de41..d7e989d37 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -446,7 +446,7 @@ namespace libtorrent std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds , m_web_seeds.begin())); - m_state = torrent_status::queued_for_checking; + set_state(torrent_status::queued_for_checking); if (m_resume_entry.type() == lazy_entry::dict_t) { @@ -474,7 +474,7 @@ namespace libtorrent if (error) { std::vector().swap(m_resume_data); - m_resume_entry = lazy_entry(); + lazy_entry().swap(m_resume_entry); } else { @@ -505,6 +505,10 @@ namespace libtorrent } m_error = j.str; pause(); + + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); + return; } @@ -627,6 +631,9 @@ namespace libtorrent // some files m_ses.check_torrent(shared_from_this()); } + + std::vector().swap(m_resume_data); + lazy_entry().swap(m_resume_entry); } void torrent::force_recheck() @@ -647,13 +654,13 @@ 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; - m_state = torrent_status::queued_for_checking; + set_state(torrent_status::queued_for_checking); if (m_auto_managed) set_queue_position((std::numeric_limits::max)()); std::vector().swap(m_resume_data); - m_resume_entry = lazy_entry(); + lazy_entry().swap(m_resume_entry); m_storage->async_check_fastresume(&m_resume_entry , bind(&torrent::on_force_recheck , shared_from_this(), _1, _2)); @@ -684,7 +691,7 @@ namespace libtorrent void torrent::start_checking() { - m_state = torrent_status::checking_files; + set_state(torrent_status::checking_files); m_storage->async_check_files(bind( &torrent::on_piece_checked @@ -3054,7 +3061,7 @@ namespace libtorrent , "torrent has finished downloading")); } - m_state = torrent_status::finished; + set_state(torrent_status::finished); set_queue_position(-1); // we have to call completed() before we start @@ -3095,7 +3102,7 @@ namespace libtorrent INVARIANT_CHECK; TORRENT_ASSERT(!is_finished()); - m_state = torrent_status::downloading; + set_state(torrent_status::downloading); set_queue_position((std::numeric_limits::max)()); } @@ -3109,7 +3116,7 @@ namespace libtorrent // make the next tracker request // be a completed-event m_event = tracker_request::completed; - m_state = torrent_status::seeding; + set_state(torrent_status::seeding); force_tracker_request(); } @@ -3181,7 +3188,7 @@ namespace libtorrent TORRENT_ASSERT(m_torrent_file->is_valid()); INVARIANT_CHECK; - m_state = torrent_status::connecting_to_tracker; + set_state(torrent_status::connecting_to_tracker); if (!is_seed()) { @@ -4032,6 +4039,17 @@ namespace libtorrent } } + void torrent::set_state(torrent_status::state_t s) + { + if (m_state == s) return; + m_state = s; + if (m_ses.m_alerts.should_post(alert::info)) + { + m_ses.m_alerts.post_alert(state_changed_alert(get_handle() + , s, "torrent status changed")); + } + } + torrent_status torrent::status() const { INVARIANT_CHECK;