From 013ed36f0913a9d2845a5d55326af4e7cfbdf5ea Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 3 Apr 2015 20:15:48 +0000 Subject: [PATCH] landed alert_queue feature branch into trunk --- bindings/python/src/alert.cpp | 30 +- bindings/python/src/session.cpp | 14 +- docs/gen_reference_doc.py | 1 - docs/makefile | 1 - examples/client_test.cpp | 23 +- examples/session_view.cpp | 6 +- examples/session_view.hpp | 2 +- examples/upnp_test.cpp | 18 +- include/libtorrent/Makefile.am | 4 +- include/libtorrent/alert.hpp | 52 +- include/libtorrent/alert_manager.hpp | 110 ++- include/libtorrent/alert_types.hpp | 904 +++++++++--------- .../aux_/alert_manager_variadic_emplace.hpp | 56 ++ include/libtorrent/aux_/session_impl.hpp | 32 +- include/libtorrent/block_cache.hpp | 6 +- include/libtorrent/buffer.hpp | 12 + include/libtorrent/disk_buffer_pool.hpp | 8 +- include/libtorrent/disk_io_thread.hpp | 9 +- include/libtorrent/heterogeneous_queue.hpp | 219 +++++ include/libtorrent/kademlia/dht_observer.hpp | 4 + include/libtorrent/kademlia/node.hpp | 6 +- include/libtorrent/session.hpp | 105 +- ...ert_dispatcher.hpp => stack_allocator.hpp} | 77 +- include/libtorrent/torrent_handle.hpp | 50 +- src/alert.cpp | 612 +++++++++++- src/alert_manager.cpp | 177 ++-- src/block_cache.cpp | 10 +- src/create_torrent.cpp | 7 +- src/disk_buffer_pool.cpp | 28 +- src/disk_io_thread.cpp | 19 +- src/http_seed_connection.cpp | 4 +- src/kademlia/dht_tracker.cpp | 3 +- src/kademlia/get_peers.cpp | 15 +- src/kademlia/node.cpp | 30 +- src/peer_connection.cpp | 84 +- src/rss.cpp | 18 +- src/session.cpp | 43 +- src/session_impl.cpp | 351 ++++--- src/torrent.cpp | 352 ++++--- src/torrent_info.cpp | 4 +- src/web_peer_connection.cpp | 4 +- test/Jamfile | 2 + test/Makefile.am | 2 + test/setup_transfer.cpp | 46 +- test/setup_transfer.hpp | 4 +- test/swarm_suite.cpp | 25 +- test/test_alert_manager.cpp | 183 ++++ test/test_block_cache.cpp | 17 +- test/test_dht.cpp | 27 +- test/test_heterogeneous_queue.cpp | 290 ++++++ test/test_priority.cpp | 42 +- test/test_privacy.cpp | 4 +- test/test_read_piece.cpp | 10 +- test/test_remap_files.cpp | 18 +- test/test_session.cpp | 10 +- test/test_storage.cpp | 52 +- test/test_torrent.cpp | 29 +- test/test_transfer.cpp | 2 +- test/web_seed_suite.cpp | 2 +- tools/dht_put.cpp | 19 +- tools/test_coverage.sh | 1 + 61 files changed, 2902 insertions(+), 1393 deletions(-) create mode 100644 include/libtorrent/aux_/alert_manager_variadic_emplace.hpp create mode 100644 include/libtorrent/heterogeneous_queue.hpp rename include/libtorrent/{alert_dispatcher.hpp => stack_allocator.hpp} (54%) create mode 100644 test/test_alert_manager.cpp create mode 100644 test/test_heterogeneous_queue.cpp diff --git a/bindings/python/src/alert.cpp b/bindings/python/src/alert.cpp index 1f214479c..2b3f011bf 100644 --- a/bindings/python/src/alert.cpp +++ b/bindings/python/src/alert.cpp @@ -195,7 +195,10 @@ void bind_alert() class_, noncopyable>( "tracker_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("url", &tracker_alert::url) +#endif + .def("tracker_url", &tracker_alert::tracker_url) ; class_, noncopyable>( @@ -221,7 +224,10 @@ void bind_alert() ; class_, noncopyable>( "tracker_error_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("msg", &tracker_error_alert::msg) +#endif + .def_readonly("error_message", &tracker_error_alert::error_message) .def_readonly("times_in_row", &tracker_error_alert::times_in_row) .def_readonly("status_code", &tracker_error_alert::status_code) .def_readonly("error", &tracker_error_alert::error) @@ -295,7 +301,10 @@ void bind_alert() class_, noncopyable>( "storage_moved_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("path", &storage_moved_alert::path) +#endif + .def("storage_path", &storage_moved_alert::storage_path) ; class_, noncopyable>( @@ -316,15 +325,19 @@ void bind_alert() class_, noncopyable>( "url_seed_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("url", &url_seed_alert::url) .def_readonly("msg", &url_seed_alert::msg) +#endif + .def("server_url", &url_seed_alert::server_url) ; class_, noncopyable>( "file_error_alert", no_init) - .def_readonly("file", &file_error_alert::file) .def_readonly("error", &file_error_alert::error) + .def("filename", &file_error_alert::filename) #ifndef TORRENT_NO_DEPRECATE + .def_readonly("file", &file_error_alert::file) .def_readonly("msg", &file_error_alert::msg) #endif ; @@ -337,7 +350,10 @@ void bind_alert() class_, noncopyable>( "listen_failed_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("interface", &listen_failed_alert::interface) +#endif + .def("listen_interface", &listen_failed_alert::listen_interface) .def_readonly("error", &listen_failed_alert::error) .def_readonly("operation", &listen_failed_alert::operation) .def_readonly("sock_type", &listen_failed_alert::sock_type) @@ -399,7 +415,10 @@ void bind_alert() class_, noncopyable>( "scrape_failed_alert", no_init) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("msg", &scrape_failed_alert::msg) +#endif + .def("error_message", &scrape_failed_alert::error_message) ; class_, noncopyable>( @@ -426,7 +445,10 @@ void bind_alert() class_, noncopyable>( "file_renamed_alert", no_init) .def_readonly("index", &file_renamed_alert::index) +#ifndef TORRENT_NO_DEPRECATE .def_readonly("name", &file_renamed_alert::name) +#endif + .def("new_name", &file_renamed_alert::new_name) ; class_, noncopyable>( @@ -608,17 +630,17 @@ void bind_alert() class_, noncopyable>( "log_alert", no_init) - .def_readonly("msg", &log_alert::msg) + .def("msg", &log_alert::msg) ; class_, noncopyable>( "torrent_log_alert", no_init) - .def_readonly("msg", &torrent_log_alert::msg) + .def("msg", &torrent_log_alert::msg) ; class_, noncopyable>( "peer_log_alert", no_init) - .def_readonly("msg", &peer_log_alert::msg) + .def("msg", &peer_log_alert::msg) ; class_, noncopyable>( diff --git a/bindings/python/src/session.cpp b/bindings/python/src/session.cpp index b33b73663..10eb0411b 100644 --- a/bindings/python/src/session.cpp +++ b/bindings/python/src/session.cpp @@ -273,6 +273,7 @@ namespace s.async_add_torrent(p); } +#ifndef TORRENT_NO_DEPRECATE void dict_to_feed_settings(dict params, feed_settings& feed) { if (params.has_key("auto_download")) @@ -354,7 +355,6 @@ namespace return ret; } -#ifndef TORRENT_NO_DEPRECATE void start_natpmp(lt::session& s) { allow_threading_guard guard; @@ -452,6 +452,7 @@ namespace return e; } +#ifndef TORRENT_NO_DEPRECATE object pop_alert(lt::session& ses) { std::auto_ptr a; @@ -462,17 +463,18 @@ namespace return object(boost::shared_ptr(a.release())); } +#endif list pop_alerts(lt::session& ses) { - std::deque alerts; + std::vector alerts; { allow_threading_guard guard; ses.pop_alerts(&alerts); } list ret; - for (std::deque::iterator i = alerts.begin() + for (std::vector::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { ret.append(boost::shared_ptr(*i)); @@ -677,9 +679,9 @@ void bind_session() ) #endif // TORRENT_NO_DEPRECATE #endif // BOOST_NO_EXCEPTIONS - .def("add_feed", &add_feed) .def("remove_torrent", allow_threads(<::session::remove_torrent), arg("option") = 0) #ifndef TORRENT_NO_DEPRECATE + .def("add_feed", &add_feed) .def("status", allow_threads(<::session::status)) .def("set_settings", <::session::set_settings) .def("settings", <::session::settings) @@ -697,11 +699,11 @@ void bind_session() #endif .def("load_state", &load_state) .def("save_state", &save_state, (arg("entry"), arg("flags") = 0xffffffff)) - .def("pop_alert", &pop_alert) .def("pop_alerts", &pop_alerts) .def("wait_for_alert", &wait_for_alert, return_internal_reference<>()) .def("add_extension", &add_extension) #ifndef TORRENT_NO_DEPRECATE + .def("pop_alert", &pop_alert) #if TORRENT_USE_I2P .def("set_i2p_proxy", allow_threads(<::session::set_i2p_proxy)) .def("i2p_proxy", allow_threads(<::session::i2p_proxy)) @@ -789,7 +791,6 @@ void bind_session() .value("listen_reuse_address", lt::session::listen_reuse_address) .value("listen_no_system_port", lt::session::listen_no_system_port) ; -#endif class_("feed_handle") .def("update_feed", &feed_handle::update_feed) @@ -797,6 +798,7 @@ void bind_session() .def("set_settings", &set_feed_settings) .def("settings", &get_feed_settings) ; +#endif register_ptr_to_python >(); diff --git a/docs/gen_reference_doc.py b/docs/gen_reference_doc.py index 89c4cfe5d..6998271f9 100644 --- a/docs/gen_reference_doc.py +++ b/docs/gen_reference_doc.py @@ -91,7 +91,6 @@ category_mapping = { 'broadcast_socket.hpp': 'Network', 'socket.hpp': 'Network', 'socket_io.hpp': 'Network', - 'rss.hpp': 'RSS', 'bitfield.hpp': 'Utility', 'sha1_hash.hpp': 'Utility', 'hasher.hpp': 'Utility', diff --git a/docs/makefile b/docs/makefile index 84f46bb93..c11d73ff6 100644 --- a/docs/makefile +++ b/docs/makefile @@ -13,7 +13,6 @@ REFERENCE_TARGETS = \ reference-Utility \ reference-Bencoding \ reference-Alerts \ - reference-RSS \ reference-Filter \ reference-Settings \ reference-Bdecoding \ diff --git a/examples/client_test.cpp b/examples/client_test.cpp index b8887c86e..ff9a8d937 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -922,15 +922,16 @@ bool handle_alert(libtorrent::session& ses, libtorrent::alert* a if (session_stats_alert* s = alert_cast(a)) { - ses_view.update_counters(s->values, s->timestamp); + ses_view.update_counters(s->values, sizeof(s->values)/sizeof(s->values[0]) + , duration_cast(s->timestamp().time_since_epoch()).count()); return true; } #ifndef TORRENT_DISABLE_DHT if (dht_stats_alert* p = alert_cast(a)) { - dht_active_requests.swap(p->active_requests); - dht_routing_table.swap(p->routing_table); + dht_active_requests = p->active_requests; + dht_routing_table = p->routing_table; return true; } #endif @@ -1959,10 +1960,10 @@ int main(int argc, char* argv[]) } // loop through the alert queue to see if anything has happened. - std::deque alerts; + std::vector alerts; ses.pop_alerts(&alerts); std::string now = timestamp(); - for (std::deque::iterator i = alerts.begin() + for (std::vector::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { TORRENT_TRY @@ -1976,7 +1977,6 @@ int main(int argc, char* argv[]) if (events.size() >= 20) events.pop_front(); } } TORRENT_CATCH(std::exception& e) {} - delete *i; } alerts.clear(); @@ -2323,16 +2323,13 @@ int main(int argc, char* argv[]) alert const* a = ses.wait_for_alert(seconds(10)); if (a == 0) continue; - std::deque alerts; + std::vector alerts; ses.pop_alerts(&alerts); std::string now = timestamp(); - for (std::deque::iterator i = alerts.begin() + for (std::vector::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { - // make sure to delete each alert - std::auto_ptr a(*i); - - torrent_paused_alert const* tp = alert_cast(*i); + torrent_paused_alert* tp = alert_cast(*i); if (tp) { ++num_paused; @@ -2350,7 +2347,7 @@ int main(int argc, char* argv[]) continue; } - save_resume_data_alert const* rd = alert_cast(*i); + save_resume_data_alert* rd = alert_cast(*i); if (!rd) continue; --num_outstanding_resume_data; printf("\rleft: %d failed: %d pause: %d " diff --git a/examples/session_view.cpp b/examples/session_view.cpp index 58c489628..a2bcece5b 100644 --- a/examples/session_view.cpp +++ b/examples/session_view.cpp @@ -182,8 +182,8 @@ void session_view::render() } } -void session_view::update_counters(std::vector& stats_counters - , boost::uint64_t t) +void session_view::update_counters(boost::uint64_t* stats_counters + , int num_cnt, boost::uint64_t t) { // only update the previous counters if there's been enough // time since it was last updated @@ -193,7 +193,7 @@ void session_view::update_counters(std::vector& stats_counters m_timestamp[1] = m_timestamp[0]; } - m_cnt[0].swap(stats_counters); + m_cnt[0].assign(stats_counters, stats_counters + num_cnt); m_timestamp[0] = t; render(); } diff --git a/examples/session_view.hpp b/examples/session_view.hpp index 33d269438..590787dfd 100644 --- a/examples/session_view.hpp +++ b/examples/session_view.hpp @@ -20,7 +20,7 @@ struct session_view void print_utp_stats(bool p) { m_print_utp_stats = p; } bool print_utp_stats() const { return m_print_utp_stats; } - void update_counters(std::vector& stats_counters + void update_counters(boost::uint64_t* stats_counters, int num_cnt , boost::uint64_t t); private: diff --git a/examples/upnp_test.cpp b/examples/upnp_test.cpp index 5da3bfb4c..d7bfa90e2 100644 --- a/examples/upnp_test.cpp +++ b/examples/upnp_test.cpp @@ -86,8 +86,13 @@ int main(int argc, char* argv[]) s.apply_settings(p); break; } - std::auto_ptr holder = s.pop_alert(); - print_alert(holder.get()); + std::vector alerts; + s.pop_alerts(&alerts); + for (std::vector::iterator i = alerts.begin() + , end(alerts.end()); i != end; ++i) + { + print_alert(*i); + } } printf("\x1b[1m\n\n===================== done mapping. Now deleting mappings ========================\n\n\n\x1b[0m"); @@ -96,8 +101,13 @@ int main(int argc, char* argv[]) { alert const* a = s.wait_for_alert(seconds(5)); if (a == 0) break; - std::auto_ptr holder = s.pop_alert(); - print_alert(holder.get()); + std::vector alerts; + s.pop_alerts(&alerts); + for (std::vector::iterator i = alerts.begin() + , end(alerts.end()); i != end; ++i) + { + print_alert(*i); + } } diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 4b4ba7610..5720eae16 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -6,7 +6,6 @@ nobase_include_HEADERS = \ alert.hpp \ alert_manager.hpp \ alert_observer.hpp \ - alert_dispatcher.hpp \ alert_types.hpp \ alloca.hpp \ allocator.hpp \ @@ -57,6 +56,7 @@ nobase_include_HEADERS = \ gzip.hpp \ hasher.hpp \ hex.hpp \ + heterogeneous_queue.hpp \ http_connection.hpp \ http_parser.hpp \ http_seed_connection.hpp \ @@ -119,6 +119,7 @@ nobase_include_HEADERS = \ socket_type_fwd.hpp \ socks5_stream.hpp \ ssl_stream.hpp \ + stack_allocator.hpp \ stat.hpp \ stat_cache.hpp \ storage.hpp \ @@ -153,6 +154,7 @@ nobase_include_HEADERS = \ tommath_class.h \ tommath_superclass.h \ \ + aux_/alert_manager_variadic_emplace.hpp \ aux_/session_call.hpp \ aux_/session_impl.hpp \ aux_/session_settings.hpp \ diff --git a/include/libtorrent/alert.hpp b/include/libtorrent/alert.hpp index 7291caa00..70393a4e4 100644 --- a/include/libtorrent/alert.hpp +++ b/include/libtorrent/alert.hpp @@ -52,21 +52,27 @@ POSSIBILITY OF SUCH DAMAGE. // // The pop_alerts() function on session is the main interface for retrieving // alerts (warnings, messages and errors from libtorrent). If no alerts have -// been posted by libtorrent pop_alert() will return an empty list. +// been posted by libtorrent pop_alerts() will return an empty list. // // By default, only errors are reported. set_alert_mask() can be used to // specify which kinds of events should be reported. The alert mask is // comprised by bits from the category_t enum. // -// Every alert belongs to one or more category. There is a small cost involved -// in posting alerts. Only alerts that belong to an enabled category are +// Every alert belongs to one or more category. There is a cost associated with +// posting alerts. Only alerts that belong to an enabled category are // posted. Setting the alert bitmask to 0 will disable all alerts (except those -// that are non-discardable). +// that are non-discardable). Alerts that are responses to API calls such as +// save_resume_data() and post_session_stats() are non-discardable and will be +// posted even if their category is disabled. // // There are other alert base classes that some alerts derive from, all the // alerts that are generated for a specific torrent are derived from // torrent_alert, and tracker events derive from tracker_alert. // +// Alerts returned by pop_alerts() are only valid until the next call to +// pop_alerts(). You may not copy an alert object to access it after the next +// call to pop_alerts(). Internal members of alerts also become invalid once +// pop_alerts() is called again. #ifdef _MSC_VER #pragma warning(pop) @@ -208,22 +214,25 @@ namespace libtorrent { // // .. code:: c++ // - // std::auto_ptr a = ses.pop_alert(); - // switch (a->type()) - // { - // case read_piece_alert::alert_type: - // { - // read_piece_alert* p = (read_piece_alert*)a.get(); - // if (p->ec) { - // // read_piece failed + // std::vector alerts; + // ses.pop_alerts(&alerts); + // for (alert* i : alerts) { + // switch (a->type()) { + // + // case read_piece_alert::alert_type: + // { + // read_piece_alert* p = (read_piece_alert*)a; + // if (p->ec) { + // // read_piece failed + // break; + // } + // // use p // break; // } - // // use p - // break; - // } - // case file_renamed_alert::alert_type: - // { - // // etc... + // case file_renamed_alert::alert_type: + // { + // // etc... + // } // } // } virtual int type() const = 0; @@ -242,18 +251,19 @@ namespace libtorrent { // returns a bitmask specifying which categories this alert belong to. virtual int category() const = 0; +#ifndef TORRENT_NO_DEPRECATE // determines whether or not an alert is allowed to be discarded // when the alert queue is full. There are a few alerts which may not be discared, // since they would break the user contract, such as save_resume_data_alert. - virtual bool discardable() const { return true; } + TORRENT_DEPRECATED_PREFIX + virtual bool discardable() const TORRENT_DEPRECATED { return true; } -#ifndef TORRENT_NO_DEPRECATE TORRENT_DEPRECATED_PREFIX severity_t severity() const TORRENT_DEPRECATED { return warning; } -#endif // returns a pointer to a copy of the alert. virtual std::auto_ptr clone() const = 0; +#endif private: time_point m_timestamp; diff --git a/include/libtorrent/alert_manager.hpp b/include/libtorrent/alert_manager.hpp index 3cd08175a..cb564b90e 100644 --- a/include/libtorrent/alert_manager.hpp +++ b/include/libtorrent/alert_manager.hpp @@ -36,10 +36,19 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/alert.hpp" #include "libtorrent/thread.hpp" +#include "libtorrent/heterogeneous_queue.hpp" +#include "libtorrent/stack_allocator.hpp" +#ifndef TORRENT_NO_DEPRECATE #include +#endif +#include #include #include +#include // for std::forward + +// used for emplace_alert() variadic template emulation for c++98 +#define TORRENT_ALERT_MANAGER_MAX_ARITY 7 namespace libtorrent { @@ -54,26 +63,66 @@ namespace libtorrent { , boost::uint32_t alert_mask = alert::error_notification); ~alert_manager(); - void post_alert(const alert& alert_); - void post_alert_ptr(alert* alert_); +#if __cplusplus >= 201103L + + template + void emplace_alert(Args&&... args) + { + mutex::scoped_lock lock(m_mutex); +#ifndef TORRENT_NO_DEPRECATE + if (m_dispatch) + { + m_dispatch(std::auto_ptr(new T(m_allocations[m_generation] + , std::forward(args)...))); + return; + } +#endif + // don't add more than this number of alerts, unless it's a + // high priority alert, in which case we try harder to deliver it + // for high priority alerts, double the upper limit + if (m_alerts[m_generation].size() >= m_queue_size_limit + * (1 + T::priority)) + return; + + T alert(m_allocations[m_generation], std::forward(args)...); + m_alerts[m_generation].push_back(alert); + + maybe_notify(lock); + } + +#else + +// emulate variadic templates for c++98 + +#include "libtorrent/aux_/alert_manager_variadic_emplace.hpp" + +#endif + bool pending() const; - std::auto_ptr get(int& num_resume); - void get_all(std::deque* alerts, int& num_resume); + void get_all(std::vector& alerts, int& num_resume); template bool should_post() const { mutex::scoped_lock lock(m_mutex); - if (m_alerts.size() >= m_queue_size_limit) return false; + if (m_alerts[m_generation].size() >= m_queue_size_limit + * (1 + T::priority)) + { + return false; + } return (m_alert_mask & T::static_category) != 0; } bool should_post(alert const* a) const { - return (m_alert_mask & a->category()) != 0; + mutex::scoped_lock lock(m_mutex); + boost::uint32_t mask = m_alert_mask; + lock.unlock(); + + return (mask & a->category()) != 0; } - alert const* wait_for_alert(time_duration max_wait); + alert* wait_for_alert(time_duration max_wait); void set_alert_mask(boost::uint32_t m) { @@ -81,12 +130,20 @@ namespace libtorrent { m_alert_mask = m; } - int alert_mask() const { return m_alert_mask; } + boost::uint32_t alert_mask() const + { + mutex::scoped_lock lock(m_mutex); + return m_alert_mask; + } size_t alert_queue_size_limit() const { return m_queue_size_limit; } size_t set_alert_queue_size_limit(size_t queue_size_limit_); + void set_notify_function(boost::function const& fun); + +#ifndef TORRENT_NO_DEPRECATE void set_dispatch_function(boost::function)> const&); +#endif int num_queued_resume() const; @@ -95,24 +152,55 @@ namespace libtorrent { #endif private: - void post_impl(std::auto_ptr& alert_, mutex::scoped_lock& l); - std::deque m_alerts; + // non-copyable + alert_manager(alert_manager const&); + alert_manager& operator=(alert_manager const&); + + void maybe_notify(mutex::scoped_lock& lock); + mutable mutex m_mutex; condition_variable m_condition; boost::uint32_t m_alert_mask; size_t m_queue_size_limit; + +#ifndef TORRENT_NO_DEPRECATE + bool maybe_dispatch(alert const& a); boost::function)> m_dispatch; +#endif + + // this function (if set) is called whenever the number of alerts in + // the alert queue goes from 0 to 1. The client is expected to wake up + // its main message loop for it to poll for alerts (using get_alerts()). + // That call will drain every alert in one atomic operation and this + // notification function will be called again the next time an alert is + // posted to the queue + boost::function m_notify; // the number of resume data alerts in the alert queue int m_num_queued_resume; + // this is either 0 or 1, it indicates which m_alerts and m_allocations + // the alert_manager is allowed to use right now. This is swapped when + // the client calls get_all(), at which point + int m_generation; + + // this is where all alerts are queued up. There are two heterogenous + // queues to double buffer the thread access. The mutex in the alert + // manager gives exclusive access to m_alerts[m_generation] and + // m_allocations[m_generation] whereas the other copy is exclusively + // used by the client thread. + heterogeneous_queue m_alerts[2]; + + // this is a stack where alerts can allocate variable length content, + // such as strings, to go with the alerts. + aux::stack_allocator m_allocations[2]; + #ifndef TORRENT_DISABLE_EXTENSIONS typedef std::list > ses_extension_list_t; ses_extension_list_t m_ses_extensions; #endif }; - } #endif diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 5850296e9..0a21c4160 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -52,6 +52,10 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { + namespace aux { + struct stack_allocator; + } + // maps an operation id (from peer_error_alert and peer_disconnected_alert) // to its name. See peer_connection for the constants TORRENT_EXPORT char const* operation_name(int op); @@ -64,7 +68,7 @@ namespace libtorrent struct TORRENT_EXPORT torrent_alert: alert { // internal - torrent_alert(torrent_handle const& h); + torrent_alert(aux::stack_allocator& alloc, torrent_handle const& h); // internal static const int alert_type = 0; @@ -73,7 +77,17 @@ namespace libtorrent // The torrent_handle pointing to the torrent this // alert is associated with. torrent_handle handle; + + char const* torrent_name() const; + +#ifndef TORRENT_NO_DEPRECATE std::string name; +#endif + + protected: + aux::stack_allocator const& m_alloc; + private: + int m_name_idx; }; // The peer alert is a base class for alerts that refer to a specific peer. It includes all @@ -81,9 +95,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_alert: torrent_alert { // internal - peer_alert(torrent_handle const& h, tcp::endpoint const& i - , peer_id const& pi) - : torrent_alert(h) + peer_alert(aux::stack_allocator& alloc, torrent_handle const& h + , tcp::endpoint const& i, peer_id const& pi) + : torrent_alert(alloc, h) , ip(i) , pid(pi) {} @@ -106,29 +120,47 @@ namespace libtorrent struct TORRENT_EXPORT tracker_alert: torrent_alert { // internal - tracker_alert(torrent_handle const& h - , std::string const& u) - : torrent_alert(h) - , url(u) - {} + tracker_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u); static const int alert_type = 2; static const int static_category = alert::tracker_notification; virtual int category() const { return static_category; } virtual std::string message() const; + // returns a null-terminated string of the tracker's URL + char const* tracker_url() const; + +#ifndef TORRENT_NO_DEPRECATE // The tracker URL std::string url; +#endif + private: + int m_url_idx; }; -#define TORRENT_DEFINE_ALERT(name, seq) \ +#ifndef TORRENT_NO_DEPRECATE + #define TORRENT_CLONE(name) \ + virtual std::auto_ptr clone() const \ + { return std::auto_ptr(new name(*this)); } +#else + #define TORRENT_CLONE(name) +#endif + +#define TORRENT_DEFINE_ALERT_IMPL(name, seq, prio) \ + static const int priority = prio; \ static const int alert_type = seq; \ virtual int type() const { return alert_type; } \ - virtual std::auto_ptr clone() const \ - { return std::auto_ptr(new name(*this)); } \ + TORRENT_CLONE(name) \ virtual int category() const { return static_category; } \ virtual char const* what() const { return #name; } +#define TORRENT_DEFINE_ALERT(name, seq) \ + TORRENT_DEFINE_ALERT_IMPL(name, seq, 0) + +#define TORRENT_DEFINE_ALERT_PRIO(name, seq) \ + TORRENT_DEFINE_ALERT_IMPL(name, seq, 1) + // The ``torrent_added_alert`` is posted once every time a torrent is successfully // added. It doesn't contain any members of its own, but inherits the torrent handle // from its base class. @@ -136,8 +168,8 @@ namespace libtorrent struct TORRENT_EXPORT torrent_added_alert: torrent_alert { // internal - torrent_added_alert(torrent_handle const& h) - : torrent_alert(h) + torrent_added_alert(aux::stack_allocator& alloc, torrent_handle const& h) + : torrent_alert(alloc, h) {} TORRENT_DEFINE_ALERT(torrent_added_alert, 3); @@ -160,15 +192,18 @@ namespace libtorrent struct TORRENT_EXPORT torrent_removed_alert: torrent_alert { // internal - torrent_removed_alert(torrent_handle const& h, sha1_hash const& ih) - : torrent_alert(h) + torrent_removed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, sha1_hash const& ih) + : torrent_alert(alloc, h) , info_hash(ih) {} - TORRENT_DEFINE_ALERT(torrent_removed_alert, 4); + TORRENT_DEFINE_ALERT_PRIO(torrent_removed_alert, 4); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif sha1_hash info_hash; }; @@ -183,25 +218,27 @@ namespace libtorrent struct TORRENT_EXPORT read_piece_alert: torrent_alert { // internal - read_piece_alert(torrent_handle const& h + read_piece_alert(aux::stack_allocator& alloc, torrent_handle const& h , int p, boost::shared_array d, int s) - : torrent_alert(h) + : torrent_alert(alloc, h) , buffer(d) , piece(p) , size(s) {} - read_piece_alert(torrent_handle h, int p, error_code e) - : torrent_alert(h) + read_piece_alert(aux::stack_allocator& alloc, torrent_handle h, int p, error_code e) + : torrent_alert(alloc, h) , ec(e) , piece(p) , size(0) {} - TORRENT_DEFINE_ALERT(read_piece_alert, 5); + TORRENT_DEFINE_ALERT_PRIO(read_piece_alert, 5); static const int static_category = alert::storage_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif error_code ec; boost::shared_array buffer; @@ -214,9 +251,9 @@ namespace libtorrent struct TORRENT_EXPORT file_completed_alert: torrent_alert { // internal - file_completed_alert(torrent_handle const& h + file_completed_alert(aux::stack_allocator& alloc, torrent_handle const& h , int idx) - : torrent_alert(h) + : torrent_alert(alloc, h) , index(idx) {} @@ -234,25 +271,26 @@ namespace libtorrent struct TORRENT_EXPORT file_renamed_alert: torrent_alert { // internal - file_renamed_alert(torrent_handle const& h + file_renamed_alert(aux::stack_allocator& alloc, torrent_handle const& h , std::string const& n - , int idx) - : torrent_alert(h) - , name(n) - , index(idx) - {} + , int idx); - TORRENT_DEFINE_ALERT(file_renamed_alert, 7); + TORRENT_DEFINE_ALERT_PRIO(file_renamed_alert, 7); static const int static_category = alert::storage_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } std::string name; +#endif + + char const* new_name() const; // refers to the index of the file that was renamed, - // ``name`` is the new name of the file. int index; + private: + int m_name_idx; }; // This is posted as a response to a torrent_handle::rename_file() call, if the rename @@ -260,20 +298,22 @@ namespace libtorrent struct TORRENT_EXPORT file_rename_failed_alert: torrent_alert { // internal - file_rename_failed_alert(torrent_handle const& h - , int idx + file_rename_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, int idx , error_code ec) - : torrent_alert(h) + : torrent_alert(alloc, h) , index(idx) , error(ec) {} - TORRENT_DEFINE_ALERT(file_rename_failed_alert, 8); + TORRENT_DEFINE_ALERT_PRIO(file_rename_failed_alert, 8); static const int static_category = alert::storage_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // refers to the index of the file that was supposed to be renamed, // ``error`` is the error code returned from the filesystem. @@ -367,9 +407,9 @@ namespace libtorrent }; // internal - performance_alert(torrent_handle const& h + performance_alert(aux::stack_allocator& alloc, torrent_handle const& h , performance_warning_t w) - : torrent_alert(h) + : torrent_alert(alloc, h) , warning_code(w) {} @@ -386,10 +426,10 @@ namespace libtorrent struct TORRENT_EXPORT state_changed_alert: torrent_alert { // internal - state_changed_alert(torrent_handle const& h + state_changed_alert(aux::stack_allocator& alloc, torrent_handle const& h , torrent_status::state_t st , torrent_status::state_t prev_st) - : torrent_alert(h) + : torrent_alert(alloc, h) , state(st) , prev_state(prev_st) {} @@ -418,20 +458,13 @@ namespace libtorrent struct TORRENT_EXPORT tracker_error_alert: tracker_alert { // internal - tracker_error_alert(torrent_handle const& h + tracker_error_alert(aux::stack_allocator& alloc + , torrent_handle const& h , int times , int status , std::string const& u , error_code const& e - , std::string const& m) - : tracker_alert(h, u) - , times_in_row(times) - , status_code(status) - , error(e) - , msg(m) - { - TORRENT_ASSERT(!url.empty()); - } + , std::string const& m); TORRENT_DEFINE_ALERT(tracker_error_alert, 11); @@ -441,7 +474,15 @@ namespace libtorrent int times_in_row; int status_code; error_code error; +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif + + // the message associated with this error + char const* error_message() const; + + private: + int m_msg_idx; }; // This alert is triggered if the tracker reply contains a warning field. @@ -450,34 +491,41 @@ namespace libtorrent struct TORRENT_EXPORT tracker_warning_alert: tracker_alert { // internal - tracker_warning_alert(torrent_handle const& h + tracker_warning_alert(aux::stack_allocator& alloc + , torrent_handle const& h , std::string const& u - , std::string const& m) - : tracker_alert(h, u) - , msg(m) - { TORRENT_ASSERT(!url.empty()); } + , std::string const& m); TORRENT_DEFINE_ALERT(tracker_warning_alert, 12); static const int static_category = alert::tracker_notification | alert::error_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE // contains the warning message from the tracker. std::string msg; +#endif + + // the message associated with this warning + char const* warning_message() const; + + private: + int m_msg_idx; }; // This alert is generated when a scrape request succeeds. struct TORRENT_EXPORT scrape_reply_alert: tracker_alert { // internal - scrape_reply_alert(torrent_handle const& h + scrape_reply_alert(aux::stack_allocator& alloc + , torrent_handle const& h , int incomp , int comp , std::string const& u) - : tracker_alert(h, u) + : tracker_alert(alloc, h, u) , incomplete(incomp) , complete(comp) - { TORRENT_ASSERT(!url.empty()); } + { TORRENT_ASSERT(!u.empty()); } TORRENT_DEFINE_ALERT(scrape_reply_alert, 13); @@ -495,27 +543,36 @@ namespace libtorrent struct TORRENT_EXPORT scrape_failed_alert: tracker_alert { // internal - scrape_failed_alert(torrent_handle const& h + scrape_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h , std::string const& u - , error_code const& e) - : tracker_alert(h, u) - , msg(convert_from_native(e.message())) - { TORRENT_ASSERT(!url.empty()); } - - scrape_failed_alert(torrent_handle const& h + , error_code const& e); + scrape_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h , std::string const& u - , std::string const& m) - : tracker_alert(h, u) - , msg(m) - { TORRENT_ASSERT(!url.empty()); } + , std::string const& m); TORRENT_DEFINE_ALERT(scrape_failed_alert, 14); static const int static_category = alert::tracker_notification | alert::error_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE // contains a message describing the error. std::string msg; +#endif + + // the error itself. This may indicate that the tracker sent an error + // message (``error::tracker_failure``), in which case it can be + // retrieved by calling ``error_message()``. + error_code error; + + // if the error indicates there is an associated message, this returns + // that message. Otherwise and empty string. + char const* error_message() const; + + private: + int m_msg_idx; }; // This alert is only for informational purpose. It is generated when a tracker announce @@ -524,12 +581,13 @@ namespace libtorrent struct TORRENT_EXPORT tracker_reply_alert: tracker_alert { // internal - tracker_reply_alert(torrent_handle const& h + tracker_reply_alert(aux::stack_allocator& alloc + , torrent_handle const& h , int np , std::string const& u) - : tracker_alert(h, u) + : tracker_alert(alloc, h, u) , num_peers(np) - { TORRENT_ASSERT(!url.empty()); } + { TORRENT_ASSERT(!u.empty()); } TORRENT_DEFINE_ALERT(tracker_reply_alert, 15); @@ -548,9 +606,10 @@ namespace libtorrent struct TORRENT_EXPORT dht_reply_alert: tracker_alert { // internal - dht_reply_alert(torrent_handle const& h + dht_reply_alert(aux::stack_allocator& alloc + , torrent_handle const& h , int np) - : tracker_alert(h, "") + : tracker_alert(alloc, h, "") , num_peers(np) {} @@ -567,11 +626,12 @@ namespace libtorrent struct TORRENT_EXPORT tracker_announce_alert: tracker_alert { // internal - tracker_announce_alert(torrent_handle const& h + tracker_announce_alert(aux::stack_allocator& alloc + , torrent_handle const& h , std::string const& u, int e) - : tracker_alert(h, u) + : tracker_alert(alloc, h, u) , event(e) - { TORRENT_ASSERT(!url.empty()); } + { TORRENT_ASSERT(!u.empty()); } TORRENT_DEFINE_ALERT(tracker_announce_alert, 17); @@ -591,10 +651,9 @@ namespace libtorrent struct TORRENT_EXPORT hash_failed_alert: torrent_alert { // internal - hash_failed_alert( - torrent_handle const& h + hash_failed_alert(aux::stack_allocator& alloc, torrent_handle const& h , int index) - : torrent_alert(h) + : torrent_alert(alloc, h) , piece_index(index) { TORRENT_ASSERT(index >= 0);} @@ -611,9 +670,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_ban_alert: peer_alert { // internal - peer_ban_alert(torrent_handle h, tcp::endpoint const& ep - , peer_id const& peer_id) - : peer_alert(h, ep, peer_id) + peer_ban_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id) + : peer_alert(alloc, h, ep, peer_id) {} TORRENT_DEFINE_ALERT(peer_ban_alert, 19); @@ -626,9 +685,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_unsnubbed_alert: peer_alert { // internal - peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const& ep - , peer_id const& peer_id) - : peer_alert(h, ep, peer_id) + peer_unsnubbed_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id) + : peer_alert(alloc, h, ep, peer_id) {} TORRENT_DEFINE_ALERT(peer_unsnubbed_alert, 20); @@ -641,9 +700,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_snubbed_alert: peer_alert { // internal - peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ep - , peer_id const& peer_id) - : peer_alert(h, ep, peer_id) + peer_snubbed_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id) + : peer_alert(alloc, h, ep, peer_id) {} TORRENT_DEFINE_ALERT(peer_snubbed_alert, 21); @@ -656,16 +715,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_error_alert: peer_alert { // internal - peer_error_alert(torrent_handle const& h, tcp::endpoint const& ep - , peer_id const& peer_id, int op, error_code const& e) - : peer_alert(h, ep, peer_id) - , operation(op) - , error(e) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + peer_error_alert(aux::stack_allocator& alloc, torrent_handle const& h + , tcp::endpoint const& ep, peer_id const& peer_id, int op + , error_code const& e); TORRENT_DEFINE_ALERT(peer_error_alert, 22); @@ -688,11 +740,8 @@ namespace libtorrent struct TORRENT_EXPORT peer_connect_alert: peer_alert { // internal - peer_connect_alert(torrent_handle h, tcp::endpoint const& ep - , peer_id const& peer_id, int type) - : peer_alert(h, ep, peer_id) - , socket_type(type) - {} + peer_connect_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int type); TORRENT_DEFINE_ALERT(peer_connect_alert, 23); @@ -707,19 +756,10 @@ namespace libtorrent struct TORRENT_EXPORT peer_disconnected_alert: peer_alert { // internal - peer_disconnected_alert(torrent_handle const& h, tcp::endpoint const& ep + peer_disconnected_alert(aux::stack_allocator& alloc + , torrent_handle const& h, tcp::endpoint const& ep , peer_id const& peer_id, operation_t op, int type, error_code const& e - , close_reason_t r) - : peer_alert(h, ep, peer_id) - , socket_type(type) - , operation(op) - , error(e) - , reason(r) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + , close_reason_t r); TORRENT_DEFINE_ALERT(peer_disconnected_alert, 24); @@ -750,11 +790,9 @@ namespace libtorrent struct TORRENT_EXPORT invalid_request_alert: peer_alert { // internal - invalid_request_alert(torrent_handle const& h, tcp::endpoint const& ep - , peer_id const& peer_id, peer_request const& r) - : peer_alert(h, ep, peer_id) - , request(r) - {} + invalid_request_alert(aux::stack_allocator& alloc + , torrent_handle const& h, tcp::endpoint const& ep + , peer_id const& peer_id, peer_request const& r); TORRENT_DEFINE_ALERT(invalid_request_alert, 25); @@ -769,16 +807,13 @@ namespace libtorrent struct TORRENT_EXPORT torrent_finished_alert: torrent_alert { // internal - torrent_finished_alert( - const torrent_handle& h) - : torrent_alert(h) - {} + torrent_finished_alert(aux::stack_allocator& alloc, + torrent_handle h); TORRENT_DEFINE_ALERT(torrent_finished_alert, 26); static const int static_category = alert::status_notification; - virtual std::string message() const - { return torrent_alert::message() + " torrent finished downloading"; } + virtual std::string message() const; }; // this alert is posted every time a piece completes downloading @@ -787,10 +822,10 @@ namespace libtorrent struct TORRENT_EXPORT piece_finished_alert: torrent_alert { // internal - piece_finished_alert( - const torrent_handle& h + piece_finished_alert(aux::stack_allocator& alloc, + torrent_handle h , int piece_num) - : torrent_alert(h) + : torrent_alert(alloc, h) , piece_index(piece_num) { TORRENT_ASSERT(piece_index >= 0);} @@ -807,12 +842,9 @@ namespace libtorrent struct TORRENT_EXPORT request_dropped_alert: peer_alert { // internal - request_dropped_alert(const torrent_handle& h, tcp::endpoint const& ep - , peer_id const& peer_id, int block_num, int piece_num) - : peer_alert(h, ep, peer_id) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + request_dropped_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num); TORRENT_DEFINE_ALERT(request_dropped_alert, 28); @@ -828,12 +860,9 @@ namespace libtorrent struct TORRENT_EXPORT block_timeout_alert: peer_alert { // internal - block_timeout_alert(const torrent_handle& h, tcp::endpoint const& ep - , peer_id const& peer_id, int block_num, int piece_num) - : peer_alert(h, ep, peer_id) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + block_timeout_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num); TORRENT_DEFINE_ALERT(block_timeout_alert, 29); @@ -849,12 +878,9 @@ namespace libtorrent struct TORRENT_EXPORT block_finished_alert: peer_alert { // internal - block_finished_alert(const torrent_handle& h, tcp::endpoint const& ep - , peer_id const& peer_id, int block_num, int piece_num) - : peer_alert(h, ep, peer_id) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + block_finished_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num); TORRENT_DEFINE_ALERT(block_finished_alert, 30); @@ -869,15 +895,9 @@ namespace libtorrent struct TORRENT_EXPORT block_downloading_alert: peer_alert { // internal - block_downloading_alert(const torrent_handle& h, tcp::endpoint const& ep - , peer_id const& peer_id, int block_num, int piece_num) - : peer_alert(h, ep, peer_id) -#ifndef TORRENT_NO_DEPRECATE - , peer_speedmsg("") -#endif - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); } + block_downloading_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep + , peer_id const& peer_id, int block_num, int piece_num); TORRENT_DEFINE_ALERT(block_downloading_alert, 31); @@ -896,12 +916,9 @@ namespace libtorrent struct TORRENT_EXPORT unwanted_block_alert: peer_alert { // internal - unwanted_block_alert(const torrent_handle& h, tcp::endpoint const& ep - , peer_id const& peer_id, int block_num, int piece_num) - : peer_alert(h, ep, peer_id) - , block_index(block_num) - , piece_index(piece_num) - { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} + unwanted_block_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep + , peer_id const& peer_id, int block_num, int piece_num); TORRENT_DEFINE_ALERT(unwanted_block_alert, 32); @@ -918,21 +935,23 @@ namespace libtorrent struct TORRENT_EXPORT storage_moved_alert: torrent_alert { // internal - storage_moved_alert(torrent_handle const& h, std::string const& p) - : torrent_alert(h) - , path(p) - {} + storage_moved_alert(aux::stack_allocator& alloc + , torrent_handle const& h, std::string const& p); TORRENT_DEFINE_ALERT(storage_moved_alert, 33); static const int static_category = alert::storage_notification; - virtual std::string message() const - { - return torrent_alert::message() + " moved storage to: " - + path; - } + virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE std::string path; +#endif + + // the path the torrent was moved to + char const* storage_path() const; + + private: + int m_path_idx; }; // The ``storage_moved_failed_alert`` is generated when an attempt to move the storage, @@ -940,35 +959,32 @@ namespace libtorrent struct TORRENT_EXPORT storage_moved_failed_alert: torrent_alert { // internal - storage_moved_failed_alert(torrent_handle const& h + storage_moved_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h , error_code const& e , std::string const& file - , char const* op) - : torrent_alert(h) - , error(e) - , file(file) - , operation(op) - {} + , char const* op); TORRENT_DEFINE_ALERT(storage_moved_failed_alert, 34); static const int static_category = alert::storage_notification; - virtual std::string message() const - { - return torrent_alert::message() + " storage move failed. " - + (operation?operation:"") + " (" + file + "): " - + convert_from_native(error.message()); - } + virtual std::string message() const; error_code error; - // If the error happened for a speific file, ``file`` is its path. If the error - // happened in a specific disk operation. +#ifndef TORRENT_NO_DEPRECATE + // If the error happened for a speific file, ``file`` is its path. std::string file; +#endif - // a NULL terminated string - // naming which one, otherwise it's NULL. + // If the error happened for a speific file, this returns its path. + char const* file_path() const; + + // If the error happened in a specific disk operation this is a NULL + // terminated string naming which one, otherwise it's NULL. char const* operation; + private: + int m_file_idx; }; // This alert is generated when a request to delete the files of a torrent complete. @@ -983,16 +999,17 @@ namespace libtorrent struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert { // internal - torrent_deleted_alert(torrent_handle const& h, sha1_hash const& ih) - : torrent_alert(h) - { info_hash = ih; } + torrent_deleted_alert(aux::stack_allocator& alloc + , torrent_handle const& h, sha1_hash const& ih); - TORRENT_DEFINE_ALERT(torrent_deleted_alert, 35); + TORRENT_DEFINE_ALERT_PRIO(torrent_deleted_alert, 35); static const int static_category = alert::storage_notification; - virtual std::string message() const - { return torrent_alert::message() + " deleted"; } + virtual std::string message() const; + +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif sha1_hash info_hash; }; @@ -1002,26 +1019,18 @@ namespace libtorrent struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert { // internal - torrent_delete_failed_alert(torrent_handle const& h, error_code const& e, sha1_hash const& ih) - : torrent_alert(h) - , error(e) - , info_hash(ih) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + torrent_delete_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, error_code const& e, sha1_hash const& ih); - TORRENT_DEFINE_ALERT(torrent_delete_failed_alert, 36); + TORRENT_DEFINE_ALERT_PRIO(torrent_delete_failed_alert, 36); static const int static_category = alert::storage_notification | alert::error_notification; - virtual std::string message() const - { - return torrent_alert::message() + " torrent deletion failed: " - +convert_from_native(error.message()); - } + virtual std::string message() const; + +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // tells you why it failed. error_code error; @@ -1039,18 +1048,18 @@ namespace libtorrent struct TORRENT_EXPORT save_resume_data_alert: torrent_alert { // internal - save_resume_data_alert(boost::shared_ptr const& rd - , torrent_handle const& h) - : torrent_alert(h) - , resume_data(rd) - {} + save_resume_data_alert(aux::stack_allocator& alloc + , boost::shared_ptr const& rd + , torrent_handle const& h); - TORRENT_DEFINE_ALERT(save_resume_data_alert, 37); + TORRENT_DEFINE_ALERT_PRIO(save_resume_data_alert, 37); static const int static_category = alert::storage_notification; - virtual std::string message() const - { return torrent_alert::message() + " resume data generated"; } + virtual std::string message() const; + +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // points to the resume data. boost::shared_ptr resume_data; @@ -1061,27 +1070,20 @@ namespace libtorrent struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert { // internal - save_resume_data_failed_alert(torrent_handle const& h - , error_code const& e) - : torrent_alert(h) - , error(e) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + save_resume_data_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, error_code const& e); - TORRENT_DEFINE_ALERT(save_resume_data_failed_alert, 38); + TORRENT_DEFINE_ALERT_PRIO(save_resume_data_failed_alert, 38); static const int static_category = alert::storage_notification | alert::error_notification; - virtual std::string message() const - { - return torrent_alert::message() + " resume data was not generated: " - + convert_from_native(error.message()); - } - virtual bool discardable() const { return false; } + virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE + virtual bool discardable() const { return false; } +#endif + + // the error code from the resume_data failure error_code error; #ifndef TORRENT_NO_DEPRECATE @@ -1095,15 +1097,12 @@ namespace libtorrent struct TORRENT_EXPORT torrent_paused_alert: torrent_alert { // internal - torrent_paused_alert(torrent_handle const& h) - : torrent_alert(h) - {} + torrent_paused_alert(aux::stack_allocator& alloc, torrent_handle const& h); TORRENT_DEFINE_ALERT(torrent_paused_alert, 39); static const int static_category = alert::status_notification; - virtual std::string message() const - { return torrent_alert::message() + " paused"; } + virtual std::string message() const; }; // This alert is generated as a response to a torrent_handle::resume() request. It is @@ -1111,14 +1110,12 @@ namespace libtorrent struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert { // internal - torrent_resumed_alert(torrent_handle const& h) - : torrent_alert(h) {} + torrent_resumed_alert(aux::stack_allocator& alloc, torrent_handle const& h); TORRENT_DEFINE_ALERT(torrent_resumed_alert, 40); static const int static_category = alert::status_notification; - virtual std::string message() const - { return torrent_alert::message() + " resumed"; } + virtual std::string message() const; }; // This alert is posted when a torrent completes checking. i.e. when it transitions @@ -1126,52 +1123,50 @@ namespace libtorrent struct TORRENT_EXPORT torrent_checked_alert: torrent_alert { // internal - torrent_checked_alert(torrent_handle const& h) - : torrent_alert(h) - {} + torrent_checked_alert(aux::stack_allocator& alloc, torrent_handle const& h); TORRENT_DEFINE_ALERT(torrent_checked_alert, 41); static const int static_category = alert::status_notification; - virtual std::string message() const - { return torrent_alert::message() + " checked"; } + virtual std::string message() const; }; // This alert is generated when a HTTP seed name lookup fails. struct TORRENT_EXPORT url_seed_alert: torrent_alert { // internal - url_seed_alert( - torrent_handle const& h - , std::string const& u - , error_code const& e) - : torrent_alert(h) - , url(u) - , msg(convert_from_native(e.message())) - {} - url_seed_alert( - torrent_handle const& h - , std::string const& u - , std::string const& m) - : torrent_alert(h) - , url(u) - , msg(m) - {} + url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u, error_code const& e); + url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u, std::string const& m); TORRENT_DEFINE_ALERT(url_seed_alert, 42); static const int static_category = alert::peer_notification | alert::error_notification; - virtual std::string message() const - { - return torrent_alert::message() + " url seed (" - + url + ") failed: " + msg; - } + std::string message() const; +#ifndef TORRENT_NO_DEPRECATE // the HTTP seed that failed std::string url; // the error message, potentially from the server std::string msg; +#endif + + // the error the web seed encountered. If this is not set, the server + // sent an error message, call ``error_message()``. + error_code error; + + // the URL the error is associated with + char const* server_url() const; + + // in case the web server sent an error message, this function returns + // it. + char const* error_message() const; + + private: + int m_url_idx; + int m_msg_idx; }; // If the storage fails to read or write files that it needs access to, this alert is @@ -1179,43 +1174,36 @@ namespace libtorrent struct TORRENT_EXPORT file_error_alert: torrent_alert { // internal - file_error_alert( - error_code const& ec + file_error_alert(aux::stack_allocator& alloc + , error_code const& ec , std::string const& file , char const* op - , torrent_handle const& h) - : torrent_alert(h) - , file(file) - , error(ec) - , operation(op) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + , torrent_handle const& h); TORRENT_DEFINE_ALERT(file_error_alert, 43); static const int static_category = alert::status_notification | alert::error_notification | alert::storage_notification; - virtual std::string message() const - { - return torrent_alert::message() + " " - + (operation?operation:"") + " (" + file - + ") error: " + convert_from_native(error.message()); - } + virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE // the path to the file that was accessed when the error occurred. std::string file; +#endif // the error code describing the error. error_code error; char const* operation; + // the file that experienced the error + char const* filename() const; + #ifndef TORRENT_NO_DEPRECATE std::string msg; #endif + private: + int m_file_idx; }; // This alert is generated when the metadata has been completely received and the info-hash @@ -1225,8 +1213,9 @@ namespace libtorrent struct TORRENT_EXPORT metadata_failed_alert: torrent_alert { // internal - metadata_failed_alert(const torrent_handle& h, error_code const& ec) - : torrent_alert(h) + metadata_failed_alert(aux::stack_allocator& alloc + , torrent_handle h, error_code const& ec) + : torrent_alert(alloc, h) , error(ec) {} @@ -1268,9 +1257,9 @@ namespace libtorrent struct TORRENT_EXPORT metadata_received_alert: torrent_alert { // internal - metadata_received_alert( - const torrent_handle& h) - : torrent_alert(h) + metadata_received_alert(aux::stack_allocator& alloc + , torrent_handle h) + : torrent_alert(alloc, h) {} TORRENT_DEFINE_ALERT(metadata_received_alert, 45); @@ -1287,7 +1276,8 @@ namespace libtorrent { // internal udp_error_alert( - udp::endpoint const& ep + aux::stack_allocator& alloc + , udp::endpoint const& ep , error_code const& ec) : endpoint(ep) , error(ec) @@ -1316,7 +1306,7 @@ namespace libtorrent struct TORRENT_EXPORT external_ip_alert: alert { // internal - external_ip_alert(address const& ip) + external_ip_alert(aux::stack_allocator& alloc, address const& ip) : external_address(ip) {} @@ -1348,24 +1338,25 @@ namespace libtorrent // internal listen_failed_alert( - std::string iface + aux::stack_allocator& alloc + , std::string iface , int op , error_code const& ec - , socket_type_t t) - : interface(iface) - , error(ec) - , operation(op) - , sock_type(t) - {} + , socket_type_t t); - TORRENT_DEFINE_ALERT(listen_failed_alert, 48); + TORRENT_DEFINE_ALERT_PRIO(listen_failed_alert, 48); static const int static_category = alert::status_notification | alert::error_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } // the interface libtorrent attempted to listen on std::string interface; +#endif + + // the interface libtorrent attempted to listen on that failed. + char const* listen_interface() const; // the error the system returned error_code error; @@ -1380,6 +1371,9 @@ namespace libtorrent // the type of listen socket this alert refers to. socket_type_t sock_type; + private: + aux::stack_allocator const& m_alloc; + int m_interface_idx; }; // This alert is posted when the listen port succeeds to be opened on a @@ -1390,16 +1384,19 @@ namespace libtorrent enum socket_type_t { tcp, tcp_ssl, udp, utp_ssl }; // internal - listen_succeeded_alert(tcp::endpoint const& ep, socket_type_t t) + listen_succeeded_alert(aux::stack_allocator& alloc, tcp::endpoint const& ep + , socket_type_t t) : endpoint(ep) , sock_type(t) {} - TORRENT_DEFINE_ALERT(listen_succeeded_alert, 49); + TORRENT_DEFINE_ALERT_PRIO(listen_succeeded_alert, 49); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // the endpoint libtorrent ended up listening on. The address // refers to the local interface and the port is the listen port. @@ -1418,7 +1415,8 @@ namespace libtorrent struct TORRENT_EXPORT portmap_error_alert: alert { // internal - portmap_error_alert(int i, int t, error_code const& e) + portmap_error_alert(aux::stack_allocator& alloc, int i, int t + , error_code const& e) : mapping(i), map_type(t), error(e) { #ifndef TORRENT_NO_DEPRECATE @@ -1453,7 +1451,7 @@ namespace libtorrent struct TORRENT_EXPORT portmap_alert: alert { // internal - portmap_alert(int i, int port, int t) + portmap_alert(aux::stack_allocator& alloc, int i, int port, int t) : mapping(i), external_port(port), map_type(t) {} @@ -1480,9 +1478,7 @@ namespace libtorrent struct TORRENT_EXPORT portmap_log_alert: alert { // internal - portmap_log_alert(int t, std::string const& m) - : map_type(t), msg(m) - {} + portmap_log_alert(aux::stack_allocator& alloc, int t, const char* m); TORRENT_DEFINE_ALERT(portmap_log_alert, 52); @@ -1490,52 +1486,59 @@ namespace libtorrent virtual std::string message() const; int map_type; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif + + // the message associated with this log line + char const* log_message() const; + + private: + + // TODO: 2 should the alert baseclass have this object instead? + aux::stack_allocator const& m_alloc; + + int m_log_idx; }; - // This alert is generated when a fastresume file has been passed to add_torrent() but the - // files on disk did not match the fastresume file. The error_code explains the reason why the - // resume file was rejected. + // This alert is generated when a fastresume file has been passed to + // add_torrent() but the files on disk did not match the fastresume file. + // The error_code explains the reason why the resume file was rejected. struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert { // internal - fastresume_rejected_alert(torrent_handle const& h + fastresume_rejected_alert(aux::stack_allocator& alloc + , torrent_handle const& h , error_code const& ec , std::string const& file - , char const* op) - : torrent_alert(h) - , error(ec) - , file(file) - , operation(op) - { -#ifndef TORRENT_NO_DEPRECATE - msg = convert_from_native(error.message()); -#endif - } + , char const* op); TORRENT_DEFINE_ALERT(fastresume_rejected_alert, 53); static const int static_category = alert::status_notification | alert::error_notification; - virtual std::string message() const - { - return torrent_alert::message() + " fast resume rejected. " - + (operation?operation:"") + "(" + file + "): " + convert_from_native(error.message()); - } + virtual std::string message() const; error_code error; - // If the error happend to a specific file, ``file`` is the path to it. If the error happened - // in a disk operation. +#ifndef TORRENT_NO_DEPRECATE + // If the error happend to a specific file, ``file`` is the path to it. std::string file; +#endif - // a NULL-terminated string of the name of that operation. - // ``operation`` is NULL otherwise. + // If the error happend to a specific file, this returns the path to it. + char const* file_path() const; + + // If the error happened in a disk operation. a NULL-terminated string of + // the name of that operation. ``operation`` is NULL otherwise. char const* operation; #ifndef TORRENT_NO_DEPRECATE std::string msg; #endif + private: + int m_path_idx; }; // This alert is posted when an incoming peer connection, or a peer that's about to be added @@ -1549,9 +1552,9 @@ namespace libtorrent struct TORRENT_EXPORT peer_blocked_alert: torrent_alert { // internal - peer_blocked_alert(torrent_handle const& h, address const& i - , int r) - : torrent_alert(h) + peer_blocked_alert(aux::stack_allocator& alloc, torrent_handle const& h + , address const& i, int r) + : torrent_alert(alloc, h) , ip(i) , reason(r) {} @@ -1583,7 +1586,7 @@ namespace libtorrent struct TORRENT_EXPORT dht_announce_alert: alert { // internal - dht_announce_alert(address const& i, int p + dht_announce_alert(aux::stack_allocator& alloc, address const& i, int p , sha1_hash const& ih) : ip(i) , port(p) @@ -1605,7 +1608,7 @@ namespace libtorrent struct TORRENT_EXPORT dht_get_peers_alert: alert { // internal - dht_get_peers_alert(sha1_hash const& ih) + dht_get_peers_alert(aux::stack_allocator& alloc, sha1_hash const& ih) : info_hash(ih) {} @@ -1623,7 +1626,7 @@ namespace libtorrent struct TORRENT_EXPORT stats_alert: torrent_alert { // internal - stats_alert(torrent_handle const& h, int interval + stats_alert(aux::stack_allocator& alloc, torrent_handle const& h, int interval , stat const& s); TORRENT_DEFINE_ALERT(stats_alert, 57); @@ -1675,7 +1678,7 @@ namespace libtorrent struct TORRENT_EXPORT cache_flushed_alert: torrent_alert { // internal - cache_flushed_alert(torrent_handle const& h); + cache_flushed_alert(aux::stack_allocator& alloc, torrent_handle const& h); TORRENT_DEFINE_ALERT(cache_flushed_alert, 58); @@ -1689,9 +1692,9 @@ namespace libtorrent struct TORRENT_EXPORT anonymous_mode_alert: torrent_alert { // internal - anonymous_mode_alert(torrent_handle const& h + anonymous_mode_alert(aux::stack_allocator& alloc, torrent_handle const& h , int k, std::string const& s) - : torrent_alert(h) + : torrent_alert(alloc, h) , kind(k) , str(s) {} @@ -1719,9 +1722,9 @@ namespace libtorrent struct TORRENT_EXPORT lsd_peer_alert: peer_alert { // internal - lsd_peer_alert(torrent_handle const& h + lsd_peer_alert(aux::stack_allocator& alloc, torrent_handle const& h , tcp::endpoint const& i) - : peer_alert(h, i, peer_id(0)) + : peer_alert(alloc, h, i, peer_id(0)) {} TORRENT_DEFINE_ALERT(lsd_peer_alert, 60); @@ -1736,27 +1739,32 @@ namespace libtorrent struct TORRENT_EXPORT trackerid_alert: tracker_alert { // internal - trackerid_alert(torrent_handle const& h + trackerid_alert(aux::stack_allocator& alloc, torrent_handle const& h , std::string const& u - , const std::string& id) - : tracker_alert(h, u) - , trackerid(id) - {} + , const std::string& id); TORRENT_DEFINE_ALERT(trackerid_alert, 61); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE // The tracker ID returned by the tracker std::string trackerid; +#endif + + // The tracker ID returned by the tracker + char const* tracker_id() const; + + private: + int m_tracker_idx; }; // This alert is posted when the initial DHT bootstrap is done. struct TORRENT_EXPORT dht_bootstrap_alert: alert { // internal - dht_bootstrap_alert() {} + dht_bootstrap_alert(aux::stack_allocator& alloc) {} TORRENT_DEFINE_ALERT(dht_bootstrap_alert, 62); @@ -1773,7 +1781,8 @@ namespace libtorrent struct TORRENT_EXPORT rss_alert: alert { // internal - rss_alert(feed_handle h, std::string const& u, int s, error_code const& ec) + rss_alert(aux::stack_allocator& alloc, feed_handle h + , std::string const& u, int s, error_code const& ec) : handle(h), url(u), state(s), error(ec) {} @@ -1817,12 +1826,8 @@ namespace libtorrent struct TORRENT_EXPORT torrent_error_alert: torrent_alert { // internal - torrent_error_alert(torrent_handle const& h - , error_code const& e, std::string const& f) - : torrent_alert(h) - , error(e) - , error_file(f) - {} + torrent_error_alert(aux::stack_allocator& alloc, torrent_handle const& h + , error_code const& e, std::string const& f); TORRENT_DEFINE_ALERT(torrent_error_alert, 64); @@ -1832,8 +1837,16 @@ namespace libtorrent // specifies which error the torrent encountered. error_code error; +#ifndef TORRENT_NO_DEPRECATE // the filename (or object) the error occurred on. std::string error_file; +#endif + + // the filename (or object) the error occurred on. + char const* filename() const; + + private: + int m_file_idx; }; // This is always posted for SSL torrents. This is a reminder to the client that @@ -1843,15 +1856,18 @@ namespace libtorrent struct TORRENT_EXPORT torrent_need_cert_alert: torrent_alert { // internal - torrent_need_cert_alert(torrent_handle const& h) - : torrent_alert(h) + torrent_need_cert_alert(aux::stack_allocator& alloc + , torrent_handle const& h) + : torrent_alert(alloc, h) {} - TORRENT_DEFINE_ALERT(torrent_need_cert_alert, 65); + TORRENT_DEFINE_ALERT_PRIO(torrent_need_cert_alert, 65); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif error_code error; }; @@ -1865,7 +1881,8 @@ namespace libtorrent struct TORRENT_EXPORT incoming_connection_alert: alert { // internal - incoming_connection_alert(int t, tcp::endpoint const& i) + incoming_connection_alert(aux::stack_allocator& alloc, int t + , tcp::endpoint const& i) : socket_type(t) , ip(i) {} @@ -1902,17 +1919,20 @@ namespace libtorrent struct TORRENT_EXPORT add_torrent_alert : torrent_alert { // internal - add_torrent_alert(torrent_handle h, add_torrent_params const& p, error_code ec) - : torrent_alert(h) + add_torrent_alert(aux::stack_allocator& alloc, torrent_handle h + , add_torrent_params const& p, error_code ec) + : torrent_alert(alloc, h) , params(p) , error(ec) {} - TORRENT_DEFINE_ALERT(add_torrent_alert, 67); + TORRENT_DEFINE_ALERT_PRIO(add_torrent_alert, 67); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // a copy of the parameters used when adding the torrent, it can be used // to identify which invocation to ``async_add_torrent()`` caused this alert. @@ -1922,28 +1942,37 @@ namespace libtorrent error_code error; }; - // This alert is only posted when requested by the user, by calling session::post_torrent_updates() - // on the session. It contains the torrent status of all torrents that changed - // since last time this message was posted. Its category is ``status_notification``, but - // it's not subject to filtering, since it's only manually posted anyway. + // This alert is only posted when requested by the user, by calling + // session::post_torrent_updates() on the session. It contains the torrent + // status of all torrents that changed since last time this message was + // posted. Its category is ``status_notification``, but it's not subject to + // filtering, since it's only manually posted anyway. struct TORRENT_EXPORT state_update_alert : alert { - TORRENT_DEFINE_ALERT(state_update_alert, 68); + state_update_alert(aux::stack_allocator& alloc, std::vector st) + : status(st) + {} + + TORRENT_DEFINE_ALERT_PRIO(state_update_alert, 68); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif - // contains the torrent status of all torrents that changed since last time - // this message was posted. Note that you can map a torrent status to a specific torrent - // via its ``handle`` member. The receiving end is suggested to have all torrents sorted - // by the torrent_handle or hashed by it, for efficient updates. + // contains the torrent status of all torrents that changed since last + // time this message was posted. Note that you can map a torrent status + // to a specific torrent via its ``handle`` member. The receiving end is + // suggested to have all torrents sorted by the torrent_handle or hashed + // by it, for efficient updates. std::vector status; }; struct TORRENT_EXPORT mmap_cache_alert : alert { - mmap_cache_alert(error_code const& ec): error(ec) {} + mmap_cache_alert(aux::stack_allocator& alloc + , error_code const& ec): error(ec) {} TORRENT_DEFINE_ALERT(mmap_cache_alert, 69); static const int static_category = alert::error_notification; @@ -1958,52 +1987,51 @@ namespace libtorrent // manually posted anyway. struct TORRENT_EXPORT session_stats_alert : alert { - session_stats_alert() {} - TORRENT_DEFINE_ALERT(session_stats_alert, 70); + session_stats_alert(aux::stack_allocator& alloc, counters const& cnt); + TORRENT_DEFINE_ALERT_PRIO(session_stats_alert, 70); static const int static_category = alert::stats_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif - // the number of microseconds since the session was - // started. It represent the time when the snapshot of values was taken. When - // the network thread is under heavy load, the latency between calling - // post_session_stats() and receiving this alert may be significant, and - // the timestamp may help provide higher accuracy in measurements. - boost::uint64_t timestamp; - - // An array are a mix of *counters* and *gauges*, which - // meanings can be queries via the session_stats_metrics() function on the session. - // The mapping from a specific metric to an index into this array is constant for a - // specific version of libtorrent, but may differ for other versions. The intended - // usage is to request the mapping, i.e. call session_stats_metrics(), once - // on startup, and then use that mapping to interpret these values throughout - // the process' runtime. + // An array are a mix of *counters* and *gauges*, which meanings can be + // queries via the session_stats_metrics() function on the session. The + // mapping from a specific metric to an index into this array is constant + // for a specific version of libtorrent, but may differ for other + // versions. The intended usage is to request the mapping, i.e. call + // session_stats_metrics(), once on startup, and then use that mapping to + // interpret these values throughout the process' runtime. // // For more information, see the session-statistics_ section. - std::vector values; + boost::uint64_t values[counters::num_counters]; }; - // When a torrent changes its info-hash, this alert is posted. This only happens in very - // specific cases. For instance, when a torrent is downloaded from a URL, the true info - // hash is not known immediately. First the .torrent file must be downloaded and parsed. + // When a torrent changes its info-hash, this alert is posted. This only + // happens in very specific cases. For instance, when a torrent is + // downloaded from a URL, the true info hash is not known immediately. First + // the .torrent file must be downloaded and parsed. // - // Once this download completes, the ``torrent_update_alert`` is posted to notify the client - // of the info-hash changing. + // Once this download completes, the ``torrent_update_alert`` is posted to + // notify the client of the info-hash changing. struct TORRENT_EXPORT torrent_update_alert : torrent_alert { // internal - torrent_update_alert(torrent_handle h, sha1_hash const& old_hash, sha1_hash const& new_hash) - : torrent_alert(h) + torrent_update_alert(aux::stack_allocator& alloc, torrent_handle h + , sha1_hash const& old_hash, sha1_hash const& new_hash) + : torrent_alert(alloc, h) , old_ih(old_hash) , new_ih(new_hash) {} - TORRENT_DEFINE_ALERT(torrent_update_alert, 71); + TORRENT_DEFINE_ALERT_PRIO(torrent_update_alert, 71); static const int static_category = alert::status_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // ``old_ih`` and ``new_ih`` are the previous and new info-hash for the torrent, respectively. sha1_hash old_ih; @@ -2019,7 +2047,8 @@ namespace libtorrent struct TORRENT_EXPORT rss_item_alert : alert { // internal - rss_item_alert(feed_handle h, feed_item const& item) + rss_item_alert(aux::stack_allocator& alloc, feed_handle h + , feed_item const& item) : handle(h) , item(item) {} @@ -2039,7 +2068,7 @@ namespace libtorrent struct TORRENT_EXPORT dht_error_alert: alert { // internal - dht_error_alert(int op, error_code const& ec) + dht_error_alert(aux::stack_allocator& alloc, int op, error_code const& ec) : error(ec), operation(op_t(op)) {} TORRENT_DEFINE_ALERT(dht_error_alert, 73); @@ -2065,15 +2094,19 @@ namespace libtorrent // specifically the overload for looking up immutable items in the DHT. struct TORRENT_EXPORT dht_immutable_item_alert: alert { - dht_immutable_item_alert(sha1_hash const& t, entry const& i) + dht_immutable_item_alert(aux::stack_allocator& alloc, sha1_hash const& t + , entry const& i) : target(t), item(i) {} - TORRENT_DEFINE_ALERT(dht_immutable_item_alert, 74); + TORRENT_DEFINE_ALERT_PRIO(dht_immutable_item_alert, 74); static const int static_category = alert::error_notification | alert::dht_notification; + virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // the target hash of the immutable item. This must // match the sha-1 hash of the bencoded form of ``item``. @@ -2087,19 +2120,22 @@ namespace libtorrent // specifically the overload for looking up mutable items in the DHT. struct TORRENT_EXPORT dht_mutable_item_alert: alert { - dht_mutable_item_alert(boost::array k + dht_mutable_item_alert(aux::stack_allocator& alloc + , boost::array k , boost::array sig , boost::uint64_t sequence , std::string const& s , entry const& i) : key(k), signature(sig), seq(sequence), salt(s), item(i) {} - TORRENT_DEFINE_ALERT(dht_mutable_item_alert, 75); + TORRENT_DEFINE_ALERT_PRIO(dht_mutable_item_alert, 75); static const int static_category = alert::error_notification | alert::dht_notification; virtual std::string message() const; +#ifndef TORRENT_NO_DEPRECATE virtual bool discardable() const { return false; } +#endif // the public key that was looked up boost::array key; @@ -2127,11 +2163,11 @@ namespace libtorrent struct TORRENT_EXPORT dht_put_alert: alert { // internal - dht_put_alert(sha1_hash const& t) + dht_put_alert(aux::stack_allocator& alloc, sha1_hash const& t) : target(t) , seq(0) {} - dht_put_alert(boost::array key + dht_put_alert(aux::stack_allocator& alloc, boost::array key , boost::array sig , std::string s , boost::uint64_t sequence_number) @@ -2162,7 +2198,7 @@ namespace libtorrent // this alert is used to report errors in the i2p SAM connection struct TORRENT_EXPORT i2p_alert : alert { - i2p_alert(error_code const& ec) : error(ec) {} + i2p_alert(aux::stack_allocator& alloc, error_code const& ec) : error(ec) {} TORRENT_DEFINE_ALERT(i2p_alert, 77); @@ -2178,7 +2214,8 @@ namespace libtorrent struct TORRENT_EXPORT dht_outgoing_get_peers_alert: alert { // internal - dht_outgoing_get_peers_alert(sha1_hash const& ih, sha1_hash const& obfih + dht_outgoing_get_peers_alert(aux::stack_allocator& alloc + , sha1_hash const& ih, sha1_hash const& obfih , udp::endpoint ep) : info_hash(ih) , obfuscated_info_hash(obfih) @@ -2210,17 +2247,19 @@ namespace libtorrent struct TORRENT_EXPORT log_alert : alert { // internal - log_alert(char const* log) - : msg(log) - {} + log_alert(aux::stack_allocator& alloc, char const* log); TORRENT_DEFINE_ALERT(log_alert, 79); static const int static_category = alert::session_log_notification; virtual std::string message() const; - // the log message - std::string msg; + // returns the log message + char const* msg() const; + + private: + aux::stack_allocator const& m_alloc; + int m_str_idx; }; // This alert is posted by torrent wide events. It's meant to be used for @@ -2232,18 +2271,19 @@ namespace libtorrent struct TORRENT_EXPORT torrent_log_alert : torrent_alert { // internal - torrent_log_alert(torrent_handle h, char const* log) - : torrent_alert(h) - , msg(log) - {} + torrent_log_alert(aux::stack_allocator& alloc, torrent_handle h + , char const* log); TORRENT_DEFINE_ALERT(torrent_log_alert, 80); static const int static_category = alert::torrent_log_notification; virtual std::string message() const; - // the log message - std::string msg; + // returns the log message + char const* msg() const; + + private: + int m_str_idx; }; // This alert is posted by events specific to a peer. It's meant to be used @@ -2255,19 +2295,20 @@ namespace libtorrent struct TORRENT_EXPORT peer_log_alert : peer_alert { // internal - peer_log_alert(torrent_handle const& h, tcp::endpoint const& i - , peer_id const& pi, char const* log) - : peer_alert(h, i, pi) - , msg(log) - {} + peer_log_alert(aux::stack_allocator& alloc, torrent_handle const& h + , tcp::endpoint const& i + , peer_id const& pi, char const* log); TORRENT_DEFINE_ALERT(peer_log_alert, 81); static const int static_category = alert::peer_log_notification; virtual std::string message() const; - // the log message - std::string msg; + // returns the log message + char const* msg() const; + + private: + int m_str_idx; }; // posted if the local service discovery socket fails to start properly. @@ -2275,7 +2316,7 @@ namespace libtorrent struct TORRENT_EXPORT lsd_error_alert : alert { // internal - lsd_error_alert(error_code const& ec) + lsd_error_alert(aux::stack_allocator& alloc, error_code const& ec) : alert() , error(ec) {} @@ -2350,8 +2391,12 @@ namespace libtorrent struct TORRENT_EXPORT dht_stats_alert : alert { // internal - dht_stats_alert() + dht_stats_alert(aux::stack_allocator& alloc + , std::vector const& table + , std::vector const& requests) : alert() + , active_requests(requests) + , routing_table(table) {} TORRENT_DEFINE_ALERT(dht_stats_alert, 83); @@ -2368,7 +2413,10 @@ namespace libtorrent }; +#undef TORRENT_DEFINE_ALERT_IMPL #undef TORRENT_DEFINE_ALERT +#undef TORRENT_DEFINE_ALERT_PRIO +#undef TORRENT_CLONE enum { num_alert_types = 84 }; } diff --git a/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp b/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp new file mode 100644 index 000000000..e65cfa2eb --- /dev/null +++ b/include/libtorrent/aux_/alert_manager_variadic_emplace.hpp @@ -0,0 +1,56 @@ + +#if !BOOST_PP_IS_ITERATING + +// set-up iteration + +#include +#include +#include +#include + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, TORRENT_ALERT_MANAGER_MAX_ARITY, \ + "libtorrent/aux_/alert_manager_variadic_emplace.hpp")) +#include BOOST_PP_ITERATE() + + +#else // BOOST_PP_IS_ITERATING + +// loop body + +#define I BOOST_PP_ITERATION() + + template + void emplace_alert(BOOST_PP_ENUM_BINARY_PARAMS(I, A, const& a) ) + { + mutex::scoped_lock lock(m_mutex); +#ifndef TORRENT_NO_DEPRECATE + if (m_dispatch) + { + m_dispatch(std::auto_ptr(new T(m_allocations[m_generation] + BOOST_PP_COMMA_IF(I) + BOOST_PP_ENUM_PARAMS(I, a)))); + return; + } +#endif + // don't add more than this number of alerts, unless it's a + // high priority alert, in which case we try harder to deliver it + // for high priority alerts, double the upper limit + if (m_alerts[m_generation].size() >= m_queue_size_limit + * (1 + T::priority)) + return; + + T alert(m_allocations[m_generation] + BOOST_PP_COMMA_IF(I) + BOOST_PP_ENUM_PARAMS(I, a)); + m_alerts[m_generation].push_back(alert); + + maybe_notify(lock); + } + +#undef I + +#endif + diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 05279c057..af5e5e521 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -93,7 +93,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/disk_io_job.hpp" // block_cache_reference #include "libtorrent/network_thread_pool.hpp" #include "libtorrent/peer_class_type_filter.hpp" -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/kademlia/dht_observer.hpp" #include "libtorrent/resolver.hpp" @@ -170,7 +169,6 @@ namespace libtorrent // thread started to run the main downloader loop struct TORRENT_EXTRA_EXPORT session_impl : session_interface - , alert_dispatcher , dht::dht_observer , boost::noncopyable , initialize_timer @@ -425,14 +423,14 @@ namespace libtorrent std::vector get_torrents() const; - size_t set_alert_queue_size_limit(size_t queue_size_limit_); - std::auto_ptr pop_alert(); - void pop_alerts(std::deque* alerts); - void set_alert_dispatch(boost::function)> const&); - - alert const* wait_for_alert(time_duration max_wait); + void pop_alerts(std::vector* alerts); + alert* wait_for_alert(time_duration max_wait); #ifndef TORRENT_NO_DEPRECATE + void pop_alerts(); + alert const* pop_alert(); + void pop_alerts(std::deque* alerts); + size_t set_alert_queue_size_limit(size_t queue_size_limit_); int upload_rate_limit() const; int download_rate_limit() const; int local_upload_rate_limit() const; @@ -576,6 +574,10 @@ namespace libtorrent // implements dht_observer virtual void set_external_address(address const& ip , address const& source); + virtual void get_peers(sha1_hash const& ih); + virtual void announce(sha1_hash const& ih, address const& addr, int port); + virtual void outgoing_get_peers(sha1_hash const& target + , sha1_hash const& sent_target, udp::endpoint const& ep); void set_external_address(address const& ip , int source_type, address const& source); @@ -619,9 +621,6 @@ namespace libtorrent void submit_disk_jobs(); - // implements alert_dispatcher - virtual bool post_alert(alert* a); - void update_proxy(); void update_i2p_bridge(); void update_peer_tos(); @@ -702,6 +701,17 @@ namespace libtorrent // handles delayed alerts mutable alert_manager m_alerts; +#ifndef TORRENT_NO_DEPRECATE + // the alert pointers stored in m_alerts + mutable std::vector m_alert_pointers; + + // if not all the alerts in m_alert_pointers have been delivered to + // the client. This is the offset into m_alert_pointers where the next + // alert is. If this is greater than or equal to m_alert_pointers.size() + // it means we need to request new alerts from the main thread. + mutable int m_alert_pointer_pos; +#endif + // handles disk io requests asynchronously // peers have pointers into the disk buffer // pool, and must be destructed before this diff --git a/include/libtorrent/block_cache.hpp b/include/libtorrent/block_cache.hpp index 0ab4d5dbd..fb7df7321 100644 --- a/include/libtorrent/block_cache.hpp +++ b/include/libtorrent/block_cache.hpp @@ -64,7 +64,6 @@ namespace libtorrent struct block_cache_reference; struct counters; namespace aux { struct session_settings; } - struct alert_dispatcher; #if TORRENT_USE_ASSERTS class file_storage; #endif @@ -330,8 +329,7 @@ namespace libtorrent struct TORRENT_EXTRA_EXPORT block_cache : disk_buffer_pool { block_cache(int block_size, io_service& ios - , boost::function const& trigger_trim - , alert_dispatcher* alert_disp); + , boost::function const& trigger_trim); private: @@ -447,7 +445,7 @@ namespace libtorrent #ifndef TORRENT_NO_DEPRECATE void get_stats(cache_status* ret) const; #endif - void set_settings(aux::session_settings const& sett); + void set_settings(aux::session_settings const& sett, error_code& ec); enum reason_t { ref_hashing = 0, ref_reading = 1, ref_flushing = 2 }; bool inc_block_refcount(cached_piece_entry* pe, int block, int reason); diff --git a/include/libtorrent/buffer.hpp b/include/libtorrent/buffer.hpp index 3302b13e1..92d4753d6 100644 --- a/include/libtorrent/buffer.hpp +++ b/include/libtorrent/buffer.hpp @@ -136,6 +136,18 @@ public: b.m_begin = NULL; b.m_size = b.m_capacity = 0; } + + buffer& operator=(buffer&& b) + { + if (&b == this) return *this; + std::free(m_begin); + m_begin = b.m_begin; + m_size = b.m_size; + m_capacity = b.m_capacity; + b.m_begin = NULL; + b.m_size = b.m_capacity = 0; + return *this; + } #endif buffer& operator=(buffer const& b) diff --git a/include/libtorrent/disk_buffer_pool.hpp b/include/libtorrent/disk_buffer_pool.hpp index e9a0206f7..093bba5eb 100644 --- a/include/libtorrent/disk_buffer_pool.hpp +++ b/include/libtorrent/disk_buffer_pool.hpp @@ -56,14 +56,12 @@ namespace libtorrent { namespace aux { struct session_settings; } class alert; - struct alert_dispatcher; struct disk_observer; struct TORRENT_EXTRA_EXPORT disk_buffer_pool : boost::noncopyable { disk_buffer_pool(int block_size, io_service& ios - , boost::function const& trigger_trim - , alert_dispatcher* alert_disp); + , boost::function const& trigger_trim); ~disk_buffer_pool(); #if TORRENT_USE_ASSERTS @@ -98,7 +96,7 @@ namespace libtorrent boost::uint32_t num_to_evict(int num_needed = 0); bool exceeded_max_size() const { return m_exceeded_max_size; } - void set_settings(aux::session_settings const& sett); + void set_settings(aux::session_settings const& sett, error_code& ec); struct handler_t { @@ -169,8 +167,6 @@ namespace libtorrent std::vector m_free_list; #endif - alert_dispatcher* m_post_alert; - #ifndef TORRENT_DISABLE_POOL_ALLOCATOR // if this is true, all buffers are allocated // from m_pool. If this is false, all buffers diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index ed6832718..1f55a0d57 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -61,9 +61,9 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { class alert; - struct alert_dispatcher; struct add_torrent_params; struct counters; + class alert_manager; struct cached_piece_info { @@ -281,13 +281,12 @@ namespace libtorrent , buffer_allocator_interface { disk_io_thread(io_service& ios - , alert_dispatcher* alert_disp , counters& cnt , void* userdata , int block_size = 16 * 1024); ~disk_io_thread(); - void set_settings(settings_pack* sett); + void set_settings(settings_pack* sett, alert_manager& alerts); void set_num_threads(int i, bool wait = true); void async_read(piece_manager* storage, peer_request const& r @@ -587,10 +586,6 @@ namespace libtorrent // used to rate limit disk performance warnings time_point m_last_disk_aio_performance_warning; - // function to be posted to the network thread to post - // an alert (used for performance warnings) - alert_dispatcher* m_post_alert; - // jobs that are completed are put on this queue // whenever the queue size grows from 0 to 1 // a message is posted to the network thread, which diff --git a/include/libtorrent/heterogeneous_queue.hpp b/include/libtorrent/heterogeneous_queue.hpp new file mode 100644 index 000000000..5fa4341ab --- /dev/null +++ b/include/libtorrent/heterogeneous_queue.hpp @@ -0,0 +1,219 @@ +/* + +Copyright (c) 2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_HETEROGENEOUS_QUEUE_HPP_INCLUDED +#define TORRENT_HETEROGENEOUS_QUEUE_HPP_INCLUDED + +#include + +#include +#include +#include + +#include "libtorrent/assert.hpp" + +namespace libtorrent { + + template + struct heterogeneous_queue + { + heterogeneous_queue() + : m_storage(NULL) + , m_capacity(0) + , m_size(0) + , m_num_items(0) + {} + + // TODO: 2 add emplace_back() version + template + typename boost::enable_if >::type + push_back(U const& a) + { + // the size of the type rounded up to pointer alignment + const int object_size = (sizeof(U) + sizeof(*m_storage) - 1) + / sizeof(*m_storage); + + // +1 for the length prefix + if (m_size + object_size + header_size > m_capacity) + grow_capacity(object_size); + + uintptr_t* ptr = m_storage + m_size; + + // length prefix + header_t* hdr = (header_t*)ptr; + hdr->len = object_size; + hdr->move = &move; + ptr += header_size; + + // construct in-place + new (ptr) U(a); + + // if we constructed the object without throwing any exception + // update counters to indicate the new item is in there + ++m_num_items; + m_size += header_size + object_size; + } + + void get_pointers(std::vector& out) + { + out.clear(); + + uintptr_t* ptr = m_storage; + uintptr_t const* const end = m_storage + m_size; + while (ptr < end) + { + header_t* hdr = (header_t*)ptr; + ptr += header_size; + TORRENT_ASSERT(ptr + hdr->len <= end); + out.push_back((T*)ptr); + ptr += hdr->len; + } + } + + void swap(heterogeneous_queue& rhs) + { + std::swap(m_storage, rhs.m_storage); + std::swap(m_capacity, rhs.m_capacity); + std::swap(m_size, rhs.m_size); + std::swap(m_num_items, rhs.m_num_items); + } + + int size() const { return m_num_items; } + bool empty() const { return m_num_items == 0; } + + void clear() + { + uintptr_t* ptr = m_storage; + uintptr_t const* const end = m_storage + m_size; + while (ptr < end) + { + header_t* hdr = (header_t*)ptr; + ptr += header_size; + TORRENT_ASSERT(ptr + hdr->len <= end); + T* a = (T*)ptr; + a->~T(); + ptr += hdr->len; + } + m_size = 0; + m_num_items = 0; + } + + T* front() + { + if (m_size == 0) return NULL; + + TORRENT_ASSERT(m_size > 1); + uintptr_t* ptr = m_storage; + header_t* hdr = (header_t*)ptr; + ptr += header_size; + TORRENT_ASSERT(hdr->len <= m_size); + return (T*)ptr; + } + + ~heterogeneous_queue() + { + clear(); + delete[] m_storage; + } + + private: + + // non-copyable + heterogeneous_queue(heterogeneous_queue const&); + heterogeneous_queue& operator=(heterogeneous_queue const&); + + // this header is put in front of every element. It tells us + // how many uintptr_t's it's using for its allocation, and it + // also tells us how to move this type if we need to grow our + // allocation. + struct header_t + { + int len; + void (*move)(uintptr_t* dst, uintptr_t* src); + }; + + const static int header_size = (sizeof(header_t) + sizeof(uintptr_t) + - 1) / sizeof(uintptr_t); + + void grow_capacity(int size) + { + int amount_to_grow = (std::max)(size + header_size + , (std::max)(m_capacity * 3 / 2, 128)); + + uintptr_t* new_storage = new uintptr_t[m_capacity + amount_to_grow]; + + uintptr_t* src = m_storage; + uintptr_t* dst = new_storage; + uintptr_t const* const end = m_storage + m_size; + while (src < end) + { + header_t* src_hdr = (header_t*)src; + header_t* dst_hdr = (header_t*)dst; + *dst_hdr = *src_hdr; + src += header_size; + dst += header_size; + TORRENT_ASSERT(src + src_hdr->len <= end); + // TODO: if this throws, should we do anything? + src_hdr->move(dst, src); + src += src_hdr->len; + dst += src_hdr->len; + } + + delete[] m_storage; + m_storage = new_storage; + m_capacity += amount_to_grow; + } + + template + static void move(uintptr_t* dst, uintptr_t* src) + { + U* rhs = (U*)src; +#if __cplusplus >= 201103L + new (dst) U(std::move(*rhs)); +#else + new (dst) U(*rhs); +#endif + rhs->~U(); + } + + uintptr_t* m_storage; + // number of uintptr_t's allocated under m_storage + int m_capacity; + // the number of uintptr_t's used under m_storage + int m_size; + // the number of objects allocated under m_storage + int m_num_items; + }; +} + +#endif + diff --git a/include/libtorrent/kademlia/dht_observer.hpp b/include/libtorrent/kademlia/dht_observer.hpp index 2145797f1..1e21c36bf 100644 --- a/include/libtorrent/kademlia/dht_observer.hpp +++ b/include/libtorrent/kademlia/dht_observer.hpp @@ -42,6 +42,10 @@ namespace libtorrent { namespace dht { virtual void set_external_address(address const& addr , address const& source) = 0; + virtual void get_peers(sha1_hash const& ih) = 0; + virtual void outgoing_get_peers(sha1_hash const& target + , sha1_hash const& sent_target, udp::endpoint const& ep) = 0; + virtual void announce(sha1_hash const& ih, address const& addr, int port) = 0; }; }} diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index b73ad889f..b49bcd67a 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -198,7 +198,7 @@ typedef std::map dht_immutable_table_t; typedef std::map dht_mutable_table_t; public: - node_impl(alert_dispatcher* alert_disp, udp_socket_interface* sock + node_impl(udp_socket_interface* sock , libtorrent::dht_settings const& settings, node_id nid, address const& external_address , dht_observer* observer, counters& cnt); @@ -286,8 +286,7 @@ public: libtorrent::dht_settings const& settings() const { return m_settings; } counters& stats_counters() const { return m_counters; } - void post_alert(alert* a); - + dht_observer* observer() const { return m_observer; } protected: void send_single_refresh(udp::endpoint const& ep, int bucket @@ -331,7 +330,6 @@ private: // secret random numbers used to create write tokens int m_secret[2]; - alert_dispatcher* m_post_alert; udp_socket_interface* m_sock; counters& m_counters; }; diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 131066cf7..5bc0a94f6 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -1097,62 +1097,68 @@ namespace libtorrent int max_connections() const TORRENT_DEPRECATED; TORRENT_DEPRECATED_PREFIX int max_uploads() const TORRENT_DEPRECATED; + + TORRENT_DEPRECATED_PREFIX + std::auto_ptr pop_alert() TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void pop_alerts(std::deque* alerts) TORRENT_DEPRECATED; + #endif - // ``pop_alert()`` is used to ask the session if any errors or events has - // occurred. With settings_pack::alert_mask you can filter which alerts - // to receive through ``pop_alert()``. For information about the alert - // categories, see alerts_. + // Alerts is the main mechanism for libtorrent to report errors and + // events. ``pop_alerts`` fills in the vector passed to it with pointers + // to new alerts. The session still owns these alerts and they will stay + // valid until the next time ``pop_alerts`` is called. You may not delete + // the alert objects. // - // ``pop_alerts()`` pops all pending alerts in a single call. In high - // performance environments with a very high alert churn rate, this can - // save significant amount of time compared to popping alerts one at a - // time. Each call requires one round-trip to the network thread. If - // alerts are produced in a higher rate than they can be popped (when - // popped one at a time) it's easy to get stuck in an infinite loop, - // trying to drain the alert queue. Popping the entire queue at once - // avoids this problem. - // - // However, the ``pop_alerts`` function comes with significantly more - // responsibility. You pass in an *empty* ``std::dequeue`` to it. - // If it's not empty, all elements in it will be deleted and then - // cleared. All currently pending alerts are returned by being swapped - // into the passed in container. The responsibility of deleting the - // alerts is transferred to the caller. This means you need to call - // delete for each item in the returned dequeue. It's probably a good - // idea to delete the alerts as you handle them, to save one extra pass - // over the dequeue. - // - // Alternatively, you can pass in the same container the next time you - // call ``pop_alerts``. - // - // ``wait_for_alert`` blocks until an alert is available, or for no more - // than ``max_wait`` time. If ``wait_for_alert`` returns because of the - // time-out, and no alerts are available, it returns 0. If at least one - // alert was generated, a pointer to that alert is returned. The alert is - // not popped, any subsequent calls to ``wait_for_alert`` will return the - // same pointer until the alert is popped by calling ``pop_alert``. This - // is useful for leaving any alert dispatching mechanism independent of - // this blocking call, the dispatcher can be called and it can pop the - // alert independently. - // - // .. note:: - // Although these functions are all thread-safe, popping alerts from - // multiple separate threads may introduce race conditions in that - // the thread issuing an asynchronous operation may not be the one - // receiving the alert with the result. + // It is safe to call ``pop_alerts`` from multiple different threads, as + // long as the alerts themselves are not accessed once another thread + // calls ``pop_alerts``. Doing this requires manual synchronization + // between the popping threads. // + // ``wait_for_alert`` will block the current thread for ``max_wait`` time + // duration, or until another alert is posted. If an alert is available + // at the time of the call, it returns immediately. The returned alert + // pointer is the head of the alert queue. ``wait_for_alert`` does not + // pop alerts from the queue, it merely peeks at it. The returned alert + // will stay valid until ``pop_alerts`` is called twice. The first time + // will pop it and the second will free it. + // + // If there is no alert in the queue and no alert arrives within the + // specified timeout, ``wait_for_alert`` returns NULL. + // // In the python binding, ``wait_for_alert`` takes the number of // milliseconds to wait as an integer. // - // To control the max number of alerts that's queued by the session, see + // The alert queue in the session will not grow indefinitely. Make sure + // to pop periodically to not miss notifications. To control the max + // number of alerts that's queued by the session, see // ``session_settings::alert_queue_size``. // + // Some alerts are considered so important that they are posted even when + // the alert queue is full. Some alerts are considered mandatory and cannot + // be disabled by the ``alert_mask``. For instance, // save_resume_data_alert and save_resume_data_failed_alert are always // posted, regardelss of the alert mask. - std::auto_ptr pop_alert(); - void pop_alerts(std::deque* alerts); - alert const* wait_for_alert(time_duration max_wait); + // + // To control which alerts are posted, set the alert_mask + // (settings_pack::alert_mask). + // + // the ``set_alert_notify`` function lets the client set a function object + // to be invoked every time the alert queue goes from having 0 alerts to + // 1 alert. This function is called from within libtorrent, it may be the + // main thread, or it may be from within a user call. The intention of + // of the function is that the client wakes up its main thread, to poll + // for more alerts using ``pop_alerts()``. If the notify function fails + // to do so, it won't be called again, until ``pop_alerts`` is called for + // some other reason. For instance, it could signal an eventfd, post a + // message to an HWND or some other main message pump. The actual + // retrieval of alerts should not be done in the callback. In fact, the + // callback should not block. It should not perform any expensive work. + // It really should just notify the main application thread. + void pop_alerts(std::vector* alerts); + alert* wait_for_alert(time_duration max_wait); + void set_alert_notify(boost::function const& fun); #ifndef TORRENT_NO_DEPRECATE TORRENT_DEPRECATED_PREFIX @@ -1173,20 +1179,19 @@ namespace libtorrent void set_alert_mask(boost::uint32_t m) TORRENT_DEPRECATED; TORRENT_DEPRECATED_PREFIX boost::uint32_t get_alert_mask() const TORRENT_DEPRECATED; -#endif // This sets a function to be called (from within libtorrent's netowrk // thread) every time an alert is posted. Since the function (``fun``) is - // run in libtorrent's internal thread, it may not call any of - // libtorrent's external API functions. Doing so results in a dead lock. + // run in libtorrent's internal thread, it may not block. // // The main intention with this function is to support integration with // platform-dependent message queues or signalling systems. For instance, // on windows, one could post a message to an HNWD or on linux, write to // a pipe or an eventfd. - void set_alert_dispatch(boost::function)> const& fun); + TORRENT_DEPRECATED_PREFIX + void set_alert_dispatch( + boost::function)> const& fun) TORRENT_DEPRECATED; -#ifndef TORRENT_NO_DEPRECATE // Starts and stops Local Service Discovery. This service will broadcast // the infohashes of all the non-private torrents on the local network to // look for peers on the same swarm within multicast reach. diff --git a/include/libtorrent/alert_dispatcher.hpp b/include/libtorrent/stack_allocator.hpp similarity index 54% rename from include/libtorrent/alert_dispatcher.hpp rename to include/libtorrent/stack_allocator.hpp index 52c4e0db6..7b147f3fc 100644 --- a/include/libtorrent/alert_dispatcher.hpp +++ b/include/libtorrent/stack_allocator.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2012-2014, Arvid Norberg +Copyright (c) 2015, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,21 +30,76 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TORRENT_ALERT_DISPATCHER_HPP_INCLUDED -#define TORRENT_ALERT_DISPATCHER_HPP_INCLUDED +#ifndef TORRENT_STACK_ALLOCATOR -namespace libtorrent +#include "libtorrent/assert.hpp" +#include "libtorrent/buffer.hpp" + +namespace libtorrent { namespace aux { - class alert; - struct TORRENT_EXPORT alert_dispatcher + struct stack_allocator { - // return true if the alert was swallowed (i.e. - // ownership was taken over). In this case, the - // alert will not be passed on to any one else - virtual bool post_alert(alert* a) = 0; + stack_allocator() {} + + int copy_string(std::string const& str) + { + int ret = int(m_storage.size()); + m_storage.resize(ret + str.length() + 1); + strcpy(&m_storage[ret], str.c_str()); + return ret; + } + + int copy_string(char const* str) + { + int ret = int(m_storage.size()); + int len = strlen(str); + m_storage.resize(ret + len + 1); + strcpy(&m_storage[ret], str); + return ret; + } + + int allocate(int bytes) + { + int ret = int(m_storage.size()); + m_storage.resize(ret + bytes); + return ret; + } + + char* ptr(int idx) + { + TORRENT_ASSERT(idx >= 0); + TORRENT_ASSERT(idx < int(m_storage.size())); + return &m_storage[idx]; + } + + char const* ptr(int idx) const + { + TORRENT_ASSERT(idx >= 0); + TORRENT_ASSERT(idx < int(m_storage.size())); + return &m_storage[idx]; + } + + void swap(stack_allocator& rhs) + { + m_storage.swap(rhs.m_storage); + } + + void reset() + { + m_storage.clear(); + } + + private: + + // non-copyable + stack_allocator(stack_allocator const&); + stack_allocator& operator=(stack_allocator const&); + + buffer m_storage; }; -} + +} } #endif diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index cb038dcb0..abd459b88 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -689,8 +689,7 @@ namespace libtorrent // extern int outstanding_resume_data; // global counter of outstanding resume data // std::vector handles = ses.get_torrents(); // ses.pause(); - // for (std::vector::iterator i = handles.begin(); - // i != handles.end(); ++i) + // for (torrent_handle i : handles) // { // torrent_handle& h = *i; // if (!h.is_valid()) continue; @@ -709,30 +708,35 @@ namespace libtorrent // // if we don't get an alert within 10 seconds, abort // if (a == 0) break; // - // std::auto_ptr holder = ses.pop_alert(); + // std::vector alerts; + // ses.pop_alerts(&alerts); // - // if (alert_cast(a)) - // { - // process_alert(a); - // --outstanding_resume_data; - // continue; - // } + // for (alert* i : alerts) + // { + // if (alert_cast(a)) + // { + // process_alert(a); + // --outstanding_resume_data; + // continue; + // } // - // save_resume_data_alert const* rd = alert_cast(a); - // if (rd == 0) - // { - // process_alert(a); - // continue; - // } + // save_resume_data_alert const* rd = alert_cast(a); + // if (rd == 0) + // { + // process_alert(a); + // continue; + // } // - // torrent_handle h = rd->handle; - // torrent_status st = h.status(torrent_handle::query_save_path | torrent_handle::query_name); - // std::ofstream out((st.save_path - // + "/" + st.name + ".fastresume").c_str() - // , std::ios_base::binary); - // out.unsetf(std::ios_base::skipws); - // bencode(std::ostream_iterator(out), *rd->resume_data); - // --outstanding_resume_data; + // torrent_handle h = rd->handle; + // torrent_status st = h.status(torrent_handle::query_save_path + // | torrent_handle::query_name); + // std::ofstream out((st.save_path + // + "/" + st.name + ".fastresume").c_str() + // , std::ios_base::binary); + // out.unsetf(std::ios_base::skipws); + // bencode(std::ostream_iterator(out), *rd->resume_data); + // --outstanding_resume_data; + // } // } // //.. note:: diff --git a/src/alert.cpp b/src/alert.cpp index 5dd593d30..733694633 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -42,6 +42,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/extensions.hpp" #include "libtorrent/torrent.hpp" #include "libtorrent/aux_/time.hpp" +#include "libtorrent/performance_counters.hpp" +#include "libtorrent/stack_allocator.hpp" #include "libtorrent/aux_/escape_string.hpp" // for convert_from_native @@ -53,22 +55,41 @@ namespace libtorrent { alert::~alert() {} time_point alert::timestamp() const { return m_timestamp; } - torrent_alert::torrent_alert(torrent_handle const& h) + torrent_alert::torrent_alert(aux::stack_allocator& alloc + , torrent_handle const& h) : handle(h) - , name(h.native_handle() ? h.native_handle()->name() : "") + , m_alloc(alloc) { - if (name.empty() && h.is_valid()) + std::string name_str; + if (h.native_handle()) + { + m_name_idx = alloc.copy_string(h.native_handle()->name()); + } + else if (h.is_valid()) { char msg[41]; to_hex((char const*)&h.native_handle()->info_hash()[0], 20, msg); - name = msg; + m_name_idx = alloc.copy_string(msg); } + else + { + m_name_idx = alloc.copy_string(""); + } + +#ifndef TORRENT_NO_DEPRECATE + name = torrent_name(); +#endif + } + + char const* torrent_alert::torrent_name() const + { + return m_alloc.ptr(m_name_idx); } std::string torrent_alert::message() const { if (!handle.is_valid()) return " - "; - return name; + return torrent_name(); } std::string peer_alert::message() const @@ -78,9 +99,23 @@ namespace libtorrent { + ", " + identify_client(pid) + ")"; } + tracker_alert::tracker_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , url(u) +#endif + , m_url_idx(alloc.copy_string(u)) + {} + + char const* tracker_alert::tracker_url() const + { + return m_alloc.ptr(m_url_idx); + } + std::string tracker_alert::message() const { - return torrent_alert::message() + " (" + url + ")"; + return torrent_alert::message() + " (" + tracker_url() + ")"; } std::string read_piece_alert::message() const @@ -107,11 +142,28 @@ namespace libtorrent { return msg; } + file_renamed_alert::file_renamed_alert(aux::stack_allocator& alloc + , torrent_handle const& h + , std::string const& n + , int idx) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , name(n) +#endif + , index(idx) + , m_name_idx(alloc.copy_string(n)) + {} + + char const* file_renamed_alert::new_name() const + { + return m_alloc.ptr(m_name_idx); + } + std::string file_renamed_alert::message() const { char msg[200 + TORRENT_MAX_PATH * 2]; - snprintf(msg, sizeof(msg), "%s: file %d renamed to %s", torrent_alert::message().c_str() - , index, name.c_str()); + snprintf(msg, sizeof(msg), "%s: file %d renamed to %s" + , torrent_alert::message().c_str(), index, new_name()); return msg; } @@ -155,18 +207,60 @@ namespace libtorrent { + state_str[state]; } + tracker_error_alert::tracker_error_alert(aux::stack_allocator& alloc + , torrent_handle const& h + , int times + , int status + , std::string const& u + , error_code const& e + , std::string const& m) + : tracker_alert(alloc, h, u) + , times_in_row(times) + , status_code(status) + , error(e) +#ifndef TORRENT_NO_DEPRECATE + , msg(m) +#endif + , m_msg_idx(alloc.copy_string(m)) + { + TORRENT_ASSERT(!u.empty()); + } + + char const* tracker_error_alert::error_message() const + { + return m_alloc.ptr(m_msg_idx); + } + std::string tracker_error_alert::message() const { char ret[400]; snprintf(ret, sizeof(ret), "%s (%d) %s \"%s\" (%d)" , tracker_alert::message().c_str(), status_code - , error.message().c_str(), msg.c_str(), times_in_row); + , error.message().c_str(), error_message(), times_in_row); return ret; } + tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc + , torrent_handle const& h + , std::string const& u + , std::string const& m) + : tracker_alert(alloc, h, u) +#ifndef TORRENT_NO_DEPRECATE + , msg(m) +#endif + , m_msg_idx(alloc.copy_string(m)) + { + TORRENT_ASSERT(!u.empty()); + } + + char const* tracker_warning_alert::warning_message() const + { + return m_alloc.ptr(m_msg_idx); + } + std::string tracker_warning_alert::message() const { - return tracker_alert::message() + " warning: " + msg; + return tracker_alert::message() + " warning: " + warning_message(); } std::string scrape_reply_alert::message() const @@ -177,9 +271,43 @@ namespace libtorrent { return ret; } + scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h + , std::string const& u + , error_code const& e) + : tracker_alert(alloc, h, u) +#ifndef TORRENT_NO_DEPRECATE + , msg(convert_from_native(e.message())) +#endif + , error(e) + , m_msg_idx(-1) + { + TORRENT_ASSERT(!u.empty()); + } + + scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h + , std::string const& u + , std::string const& m) + : tracker_alert(alloc, h, u) +#ifndef TORRENT_NO_DEPRECATE + , msg(m) +#endif + , error(errors::tracker_failure) + , m_msg_idx(alloc.copy_string(m)) + { + TORRENT_ASSERT(!u.empty()); + } + + char const* scrape_failed_alert::error_message() const + { + if (m_msg_idx == -1) return ""; + else return m_alloc.ptr(m_msg_idx); + } + std::string scrape_failed_alert::message() const { - return tracker_alert::message() + " scrape failed: " + msg; + return tracker_alert::message() + " scrape failed: " + error_message(); } std::string tracker_reply_alert::message() const @@ -229,6 +357,12 @@ namespace libtorrent { } + invalid_request_alert::invalid_request_alert(aux::stack_allocator& alloc + , torrent_handle const& h, tcp::endpoint const& ep + , peer_id const& peer_id, peer_request const& r) + : peer_alert(alloc, h, ep, peer_id) + , request(r) + {} std::string invalid_request_alert::message() const { @@ -238,6 +372,15 @@ namespace libtorrent { return ret; } + torrent_finished_alert::torrent_finished_alert(aux::stack_allocator& alloc, + torrent_handle h) + : torrent_alert(alloc, h) + {} + + std::string torrent_finished_alert::message() const + { + return torrent_alert::message() + " torrent finished downloading"; + } std::string piece_finished_alert::message() const { @@ -247,6 +390,15 @@ namespace libtorrent { return ret; } + request_dropped_alert::request_dropped_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num) + : peer_alert(alloc, h, ep, peer_id) + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); + } std::string request_dropped_alert::message() const { @@ -256,6 +408,16 @@ namespace libtorrent { return ret; } + block_timeout_alert::block_timeout_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num) + : peer_alert(alloc, h, ep, peer_id) + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); + } + std::string block_timeout_alert::message() const { char ret[200]; @@ -264,6 +426,16 @@ namespace libtorrent { return ret; } + block_finished_alert::block_finished_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , int piece_num) + : peer_alert(alloc, h, ep, peer_id) + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); + } + std::string block_finished_alert::message() const { char ret[200]; @@ -272,6 +444,19 @@ namespace libtorrent { return ret; } + block_downloading_alert::block_downloading_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep + , peer_id const& peer_id, int block_num, int piece_num) + : peer_alert(alloc, h, ep, peer_id) +#ifndef TORRENT_NO_DEPRECATE + , peer_speedmsg("") +#endif + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); + } + std::string block_downloading_alert::message() const { char ret[200]; @@ -280,6 +465,16 @@ namespace libtorrent { return ret; } + unwanted_block_alert::unwanted_block_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep + , peer_id const& peer_id, int block_num, int piece_num) + : peer_alert(alloc, h, ep, peer_id) + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); + } + std::string unwanted_block_alert::message() const { char ret[200]; @@ -288,6 +483,139 @@ namespace libtorrent { return ret; } + storage_moved_alert::storage_moved_alert(aux::stack_allocator& alloc + , torrent_handle const& h, std::string const& p) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , path(p) +#endif + , m_path_idx(alloc.copy_string(p)) + {} + + std::string storage_moved_alert::message() const + { + return torrent_alert::message() + " moved storage to: " + + storage_path(); + } + + char const* storage_moved_alert::storage_path() const + { + return m_alloc.ptr(m_path_idx); + } + + storage_moved_failed_alert::storage_moved_failed_alert( + aux::stack_allocator& alloc + , torrent_handle const& h + , error_code const& e + , std::string const& file + , char const* op) + : torrent_alert(alloc, h) + , error(e) +#ifndef TORRENT_NO_DEPRECATE + , file(file) +#endif + , operation(op) + , m_file_idx(alloc.copy_string(file)) + {} + + char const* storage_moved_failed_alert::file_path() const + { + return m_alloc.ptr(m_file_idx); + } + + std::string storage_moved_failed_alert::message() const + { + return torrent_alert::message() + " storage move failed. " + + (operation?operation:"") + " (" + file_path() + "): " + + convert_from_native(error.message()); + } + + torrent_deleted_alert::torrent_deleted_alert(aux::stack_allocator& alloc + , torrent_handle const& h, sha1_hash const& ih) + : torrent_alert(alloc, h) + , info_hash(ih) + {} + + std::string torrent_deleted_alert::message() const + { + return torrent_alert::message() + " deleted"; + } + + torrent_delete_failed_alert::torrent_delete_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, error_code const& e, sha1_hash const& ih) + : torrent_alert(alloc, h) + , error(e) + , info_hash(ih) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + + std::string torrent_delete_failed_alert::message() const + { + return torrent_alert::message() + " torrent deletion failed: " + +convert_from_native(error.message()); + } + + save_resume_data_alert::save_resume_data_alert(aux::stack_allocator& alloc + , boost::shared_ptr const& rd + , torrent_handle const& h) + : torrent_alert(alloc, h) + , resume_data(rd) + {} + + std::string save_resume_data_alert::message() const + { + return torrent_alert::message() + " resume data generated"; + } + + save_resume_data_failed_alert::save_resume_data_failed_alert(aux::stack_allocator& alloc + , torrent_handle const& h, error_code const& e) + : torrent_alert(alloc, h) + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + + std::string save_resume_data_failed_alert::message() const + { + return torrent_alert::message() + " resume data was not generated: " + + convert_from_native(error.message()); + } + + torrent_paused_alert::torrent_paused_alert(aux::stack_allocator& alloc + , torrent_handle const& h) + : torrent_alert(alloc, h) + {} + + std::string torrent_paused_alert::message() const + { + return torrent_alert::message() + " paused"; + } + + torrent_resumed_alert::torrent_resumed_alert(aux::stack_allocator& alloc + , torrent_handle const& h) + : torrent_alert(alloc, h) + {} + + std::string torrent_resumed_alert::message() const + { + return torrent_alert::message() + " resumed"; + } + + torrent_checked_alert::torrent_checked_alert(aux::stack_allocator& alloc + , torrent_handle const& h) + : torrent_alert(alloc, h) + {} + + std::string torrent_checked_alert::message() const + { + return torrent_alert::message() + " checked"; + } + namespace { static char const* const sock_type_str[] = @@ -311,6 +639,28 @@ namespace libtorrent { }; } + listen_failed_alert::listen_failed_alert( + aux::stack_allocator& alloc + , std::string iface + , int op + , error_code const& ec + , socket_type_t t) + : +#ifndef TORRENT_NO_DEPRECATE + interface(iface), +#endif + error(ec) + , operation(op) + , sock_type(t) + , m_alloc(alloc) + , m_interface_idx(alloc.copy_string(iface)) + {} + + char const* listen_failed_alert::listen_interface() const + { + return m_alloc.ptr(m_interface_idx); + } + std::string listen_failed_alert::message() const { static char const* op_str[] = @@ -324,7 +674,7 @@ namespace libtorrent { }; char ret[300]; snprintf(ret, sizeof(ret), "listening on %s failed: [%s] [%s] %s" - , interface.c_str() + , listen_interface() , op_str[operation] , sock_type_str[sock_type] , convert_from_native(error.message()).c_str()); @@ -353,13 +703,59 @@ namespace libtorrent { return ret; } + portmap_log_alert::portmap_log_alert(aux::stack_allocator& alloc, int t, const char* m) + : map_type(t) +#ifndef TORRENT_NO_DEPRECATE + , msg(m) +#endif + , m_alloc(alloc) + , m_log_idx(alloc.copy_string(m)) + {} + + char const* portmap_log_alert::log_message() const + { + return m_alloc.ptr(m_log_idx); + } + std::string portmap_log_alert::message() const { char ret[600]; - snprintf(ret, sizeof(ret), "%s: %s", nat_type_str[map_type], msg.c_str()); + snprintf(ret, sizeof(ret), "%s: %s", nat_type_str[map_type] + , log_message()); return ret; } + fastresume_rejected_alert::fastresume_rejected_alert( + aux::stack_allocator& alloc + , torrent_handle const& h + , error_code const& ec + , std::string const& file + , char const* op) + : torrent_alert(alloc, h) + , error(ec) +#ifndef TORRENT_NO_DEPRECATE + , file(file) +#endif + , operation(op) + , m_path_idx(alloc.copy_string(file)) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + + std::string fastresume_rejected_alert::message() const + { + return torrent_alert::message() + " fast resume rejected. " + + (operation?operation:"") + "(" + file_path() + "): " + + convert_from_native(error.message()); + } + + char const* fastresume_rejected_alert::file_path() const + { + return m_alloc.ptr(m_path_idx); + } + std::string peer_blocked_alert::message() const { error_code ec; @@ -401,8 +797,9 @@ namespace libtorrent { return msg; } - stats_alert::stats_alert(torrent_handle const& h, int in, stat const& s) - : torrent_alert(h) + stats_alert::stats_alert(aux::stack_allocator& alloc + , torrent_handle const& h, int in, stat const& s) + : torrent_alert(alloc, h) , interval(in) { transferred[upload_payload] = s[stat::upload_payload].counter(); @@ -450,7 +847,9 @@ namespace libtorrent { return msg; } - cache_flushed_alert::cache_flushed_alert(torrent_handle const& h): torrent_alert(h) {} + cache_flushed_alert::cache_flushed_alert(aux::stack_allocator& alloc + , torrent_handle const& h) + : torrent_alert(alloc, h) {} std::string anonymous_mode_alert::message() const { @@ -472,9 +871,26 @@ namespace libtorrent { return msg; } + trackerid_alert::trackerid_alert( + aux::stack_allocator& alloc + , torrent_handle const& h + , std::string const& u + , const std::string& id) + : tracker_alert(alloc, h, u) +#ifndef TORRENT_NO_DEPRECATE + , trackerid(id) +#endif + , m_tracker_idx(alloc.copy_string(id)) + {} + + char const* trackerid_alert::tracker_id() const + { + return m_alloc.ptr(m_tracker_idx); + } + std::string trackerid_alert::message() const { - return "trackerid received: " + trackerid; + return std::string("trackerid received: ") + tracker_id(); } std::string dht_bootstrap_alert::message() const @@ -493,6 +909,18 @@ namespace libtorrent { } #endif + torrent_error_alert::torrent_error_alert( + aux::stack_allocator& alloc + , torrent_handle const& h + , error_code const& e, std::string const& f) + : torrent_alert(alloc, h) + , error(e) +#ifndef TORRENT_NO_DEPRECATE + , error_file(f) +#endif + , m_file_idx(alloc.copy_string(f)) + {} + std::string torrent_error_alert::message() const { char msg[200]; @@ -524,6 +952,12 @@ namespace libtorrent { return msg; } + peer_connect_alert::peer_connect_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int type) + : peer_alert(alloc, h, ep, peer_id) + , socket_type(type) + {} + std::string peer_connect_alert::message() const { char msg[600]; @@ -573,10 +1007,22 @@ namespace libtorrent { std::string session_stats_alert::message() const { char msg[100]; - snprintf(msg, sizeof(msg), "session stats (%d values)", int(values.size())); + snprintf(msg, sizeof(msg), "session stats (%d values)", int(sizeof(values))); return msg; } + peer_error_alert::peer_error_alert(aux::stack_allocator& alloc, torrent_handle const& h + , tcp::endpoint const& ep, peer_id const& peer_id, int op + , error_code const& e) + : peer_alert(alloc, h, ep, peer_id) + , operation(op) + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + std::string peer_error_alert::message() const { char msg[200]; @@ -636,6 +1082,21 @@ namespace libtorrent { } #endif + peer_disconnected_alert::peer_disconnected_alert(aux::stack_allocator& alloc + , torrent_handle const& h, tcp::endpoint const& ep + , peer_id const& peer_id, operation_t op, int type, error_code const& e + , close_reason_t r) + : peer_alert(alloc, h, ep, peer_id) + , socket_type(type) + , operation(op) + , error(e) + , reason(r) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + std::string peer_disconnected_alert::message() const { char msg[600]; @@ -724,19 +1185,52 @@ namespace libtorrent { return msg; } + log_alert::log_alert(aux::stack_allocator& alloc, char const* log) + : m_alloc(alloc) + , m_str_idx(alloc.copy_string(log)) + {} + + char const* log_alert::msg() const + { + return m_alloc.ptr(m_str_idx); + } + std::string log_alert::message() const { - return msg; + return msg(); + } + + torrent_log_alert::torrent_log_alert(aux::stack_allocator& alloc, torrent_handle h + , char const* log) + : torrent_alert(alloc, h) + , m_str_idx(alloc.copy_string(log)) + {} + + char const* torrent_log_alert::msg() const + { + return m_alloc.ptr(m_str_idx); } std::string torrent_log_alert::message() const { - return torrent_alert::message() + ": " + msg; + return torrent_alert::message() + ": " + msg(); + } + + peer_log_alert::peer_log_alert(aux::stack_allocator& alloc, torrent_handle const& h + , tcp::endpoint const& i + , peer_id const& pi, char const* log) + : peer_alert(alloc, h, i, pi) + , m_str_idx(alloc.copy_string(log)) + {} + + char const* peer_log_alert::msg() const + { + return m_alloc.ptr(m_str_idx); } std::string peer_log_alert::message() const { - return torrent_alert::message() + " [" + print_endpoint(ip) + "] " + msg; + return torrent_alert::message() + " [" + print_endpoint(ip) + "] " + msg(); } std::string lsd_error_alert::message() const @@ -744,6 +1238,12 @@ namespace libtorrent { return "Local Service Discovery error: " + error.message(); } + session_stats_alert::session_stats_alert(aux::stack_allocator&, counters const& cnt) + { + for (int i = 0; i < counters::num_counters; ++i) + values[i] = cnt[i]; + } + std::string dht_stats_alert::message() const { char buf[2048]; @@ -753,5 +1253,75 @@ namespace libtorrent { return buf; } + url_seed_alert::url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u, error_code const& e) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , url(u) + , msg(convert_from_native(e.message())) +#endif + , error(e) + , m_url_idx(alloc.copy_string(u)) + , m_msg_idx(-1) + {} + + url_seed_alert::url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h + , std::string const& u, std::string const& m) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , url(u) + , msg(m) +#endif + , m_url_idx(alloc.copy_string(u)) + , m_msg_idx(alloc.copy_string(m)) + {} + + std::string url_seed_alert::message() const + { + return torrent_alert::message() + " url seed (" + + server_url() + ") failed: " + convert_from_native(error.message()); + } + + char const* url_seed_alert::server_url() const + { + return m_alloc.ptr(m_url_idx); + } + + char const* url_seed_alert::error_message() const + { + if (m_msg_idx == -1) return ""; + return m_alloc.ptr(m_msg_idx); + } + + file_error_alert::file_error_alert(aux::stack_allocator& alloc + , error_code const& ec + , std::string const& file + , char const* op + , torrent_handle const& h) + : torrent_alert(alloc, h) +#ifndef TORRENT_NO_DEPRECATE + , file(file) +#endif + , error(ec) + , operation(op) + , m_file_idx(alloc.copy_string(file)) + { +#ifndef TORRENT_NO_DEPRECATE + msg = convert_from_native(error.message()); +#endif + } + + char const* file_error_alert::filename() const + { + return m_alloc.ptr(m_file_idx); + } + + std::string file_error_alert::message() const + { + return torrent_alert::message() + " " + + (operation?operation:"") + " (" + filename() + + ") error: " + convert_from_native(error.message()); + } + } // namespace libtorrent diff --git a/src/alert_manager.cpp b/src/alert_manager.cpp index 2915aaa42..6d69cd6d2 100644 --- a/src/alert_manager.cpp +++ b/src/alert_manager.cpp @@ -45,20 +45,10 @@ namespace libtorrent : m_alert_mask(alert_mask) , m_queue_size_limit(queue_limit) , m_num_queued_resume(0) + , m_generation(0) {} - alert_manager::~alert_manager() - { - while (!m_alerts.empty()) - { - TORRENT_ASSERT(alert_cast(m_alerts.front()) == 0 - && "shutting down session with remaining resume data alerts in the alert queue. " - "You proabably wany to make sure you always wait for all resume data " - "alerts before shutting down"); - delete m_alerts.front(); - m_alerts.pop_front(); - } - } + alert_manager::~alert_manager() {} int alert_manager::num_queued_resume() const { @@ -66,101 +56,83 @@ namespace libtorrent return m_num_queued_resume; } - alert const* alert_manager::wait_for_alert(time_duration max_wait) + alert* alert_manager::wait_for_alert(time_duration max_wait) { mutex::scoped_lock lock(m_mutex); - if (!m_alerts.empty()) return m_alerts.front(); + if (!m_alerts[m_generation].empty()) + return m_alerts[m_generation].front(); // this call can be interrupted prematurely by other signals m_condition.wait_for(lock, max_wait); - if (!m_alerts.empty()) return m_alerts.front(); + if (!m_alerts[m_generation].empty()) + return m_alerts[m_generation].front(); return NULL; } - void alert_manager::set_dispatch_function(boost::function)> const& fun) + void alert_manager::maybe_notify(mutex::scoped_lock& lock) + { + + if (m_alerts[m_generation].size() == 1) + { + lock.unlock(); + + // we just posted to an empty queue. If anyone is waiting for + // alerts, we need to notify them. Also (potentially) call the + // user supplied m_notify callback to let the client wake up its + // message loop to poll for alerts. + if (m_notify) m_notify(); + + // TODO: 2 keep a count of the number of threads waiting. Only if it's + // > 0 notify them + m_condition.notify_all(); + } + } + +#ifndef TORRENT_NO_DEPRECATE + + bool alert_manager::maybe_dispatch(alert const& a) + { + if (m_dispatch) + { + m_dispatch(a.clone()); + return true; + } + return false; + } + + void alert_manager::set_dispatch_function( + boost::function)> const& fun) { mutex::scoped_lock lock(m_mutex); m_dispatch = fun; - std::deque alerts; - m_alerts.swap(alerts); + heterogeneous_queue storage; + m_alerts[m_generation].swap(storage); lock.unlock(); - while (!alerts.empty()) + std::vector alerts; + storage.get_pointers(alerts); + + for (std::vector::iterator i = alerts.begin() + , end(alerts.end()); i != end; ++i) { - TORRENT_TRY { - m_dispatch(std::auto_ptr(alerts.front())); - } TORRENT_CATCH(std::exception&) {} - alerts.pop_front(); + m_dispatch((*i)->clone()); } } - - void dispatch_alert(boost::function dispatcher - , alert* alert_) - { - std::auto_ptr holder(alert_); - dispatcher(*alert_); - } - - void alert_manager::post_alert_ptr(alert* alert_) - { - std::auto_ptr a(alert_); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (ses_extension_list_t::iterator i = m_ses_extensions.begin() - , end(m_ses_extensions.end()); i != end; ++i) - { - TORRENT_TRY { - (*i)->on_alert(alert_); - } TORRENT_CATCH(std::exception&) {} - } #endif - mutex::scoped_lock lock(m_mutex); - post_impl(a, lock); - } - - void alert_manager::post_alert(const alert& alert_) + void alert_manager::set_notify_function(boost::function const& fun) { - std::auto_ptr a(alert_.clone()); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (ses_extension_list_t::iterator i = m_ses_extensions.begin() - , end(m_ses_extensions.end()); i != end; ++i) - { - TORRENT_TRY { - (*i)->on_alert(&alert_); - } TORRENT_CATCH(std::exception&) {} - } -#endif - mutex::scoped_lock lock(m_mutex); - post_impl(a, lock); - } - - void alert_manager::post_impl(std::auto_ptr& alert_ - , mutex::scoped_lock& /* l */) - { - - if (alert_cast(alert_.get()) - || alert_cast(alert_.get())) - ++m_num_queued_resume; - - if (m_dispatch) + m_notify = fun; + if (!m_alerts[m_generation].empty()) { - TORRENT_ASSERT(m_alerts.empty()); - TORRENT_TRY { - m_dispatch(alert_); - } TORRENT_CATCH(std::exception&) {} - } - else if (m_alerts.size() < m_queue_size_limit || !alert_->discardable()) - { - m_alerts.push_back(alert_.release()); - if (m_alerts.size() == 1) - m_condition.notify_all(); + // never call a callback with the lock held! + lock.unlock(); + m_notify(); } } @@ -171,46 +143,29 @@ namespace libtorrent } #endif - std::auto_ptr alert_manager::get(int& num_resume) + void alert_manager::get_all(std::vector& alerts, int& num_resume) { mutex::scoped_lock lock(m_mutex); - - if (m_alerts.empty()) - return std::auto_ptr(0); + TORRENT_ASSERT(m_num_queued_resume <= m_alerts[m_generation].size()); - TORRENT_ASSERT(m_num_queued_resume <= int(m_alerts.size())); + alerts.clear(); + if (m_alerts[m_generation].empty()) return; - alert* result = m_alerts.front(); - m_alerts.pop_front(); - - if (alert_cast(result) - || alert_cast(result)) - { - --m_num_queued_resume; - num_resume = 1; - } - else - { - num_resume = 0; - } - return std::auto_ptr(result); - } - - void alert_manager::get_all(std::deque* alerts, int& num_resume) - { - mutex::scoped_lock lock(m_mutex); - TORRENT_ASSERT(m_num_queued_resume <= int(m_alerts.size())); + m_alerts[m_generation].get_pointers(alerts); num_resume = m_num_queued_resume; m_num_queued_resume = 0; - if (m_alerts.empty()) return; - m_alerts.swap(*alerts); + + // swap buffers + m_generation = (m_generation + 1) & 1; + // clear the one we will start writing to now + m_alerts[m_generation].clear(); + m_allocations[m_generation].reset(); } bool alert_manager::pending() const { mutex::scoped_lock lock(m_mutex); - - return !m_alerts.empty(); + return !m_alerts[m_generation].empty(); } size_t alert_manager::set_alert_queue_size_limit(size_t queue_size_limit_) diff --git a/src/block_cache.cpp b/src/block_cache.cpp index 1315f25ff..895d3aa73 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -41,7 +41,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/disk_io_thread.hpp" // disk_operation_failed #include "libtorrent/invariant_check.hpp" #include "libtorrent/alloca.hpp" -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/performance_counters.hpp" #include "libtorrent/aux_/time.hpp" @@ -266,9 +265,8 @@ cached_piece_entry::~cached_piece_entry() } block_cache::block_cache(int block_size, io_service& ios - , boost::function const& trigger_trim - , alert_dispatcher* alert_disp) - : disk_buffer_pool(block_size, ios, trigger_trim, alert_disp) + , boost::function const& trigger_trim) + : disk_buffer_pool(block_size, ios, trigger_trim) , m_last_cache_op(cache_miss) , m_ghost_size(8) , m_read_cache_size(0) @@ -1458,7 +1456,7 @@ void block_cache::get_stats(cache_status* ret) const } #endif -void block_cache::set_settings(aux::session_settings const& sett) +void block_cache::set_settings(aux::session_settings const& sett, error_code& ec) { // the ghost size is the number of pieces to keep track of // after they are evicted. Since cache_size is blocks, the @@ -1467,7 +1465,7 @@ void block_cache::set_settings(aux::session_settings const& sett) m_ghost_size = (std::max)(8, sett.get_int(settings_pack::cache_size) / (std::max)(sett.get_int(settings_pack::read_cache_line_size), 4) / 2); - disk_buffer_pool::set_settings(sett); + disk_buffer_pool::set_settings(sett, ec); } #if TORRENT_USE_INVARIANT_CHECKS diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 49bacd72d..3659da05b 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/disk_io_thread.hpp" #include "libtorrent/torrent_info.hpp" // for merkle_*() #include "libtorrent/performance_counters.hpp" // for counters +#include "libtorrent/alert_manager.hpp" #include #include @@ -251,7 +252,7 @@ namespace libtorrent // dummy torrent object pointer boost::shared_ptr dummy; counters cnt; - disk_io_thread disk_thread(ios, 0, cnt, 0); + disk_io_thread disk_thread(ios, cnt, 0); storage_params params; params.files = &t.files(); @@ -269,7 +270,9 @@ namespace libtorrent sett.set_int(settings_pack::cache_size, 0); sett.set_int(settings_pack::hashing_threads, 2); - disk_thread.set_settings(&sett); + // TODO: this should probably be optional + alert_manager dummy2(0, 0); + disk_thread.set_settings(&sett, dummy2); int piece_counter = 0; int completed_piece = 0; diff --git a/src/disk_buffer_pool.cpp b/src/disk_buffer_pool.cpp index 18662301b..bcebe32b7 100644 --- a/src/disk_buffer_pool.cpp +++ b/src/disk_buffer_pool.cpp @@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/io_service.hpp" #include "libtorrent/alert.hpp" #include "libtorrent/alert_types.hpp" -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/disk_observer.hpp" #include @@ -91,16 +90,8 @@ namespace libtorrent } } - // this is posted to the network thread and run from there - static void alert_callback(alert_dispatcher* disp, alert* a) - { - if (disp && disp->post_alert(a)) return; - delete a; - } - disk_buffer_pool::disk_buffer_pool(int block_size, io_service& ios - , boost::function const& trigger_trim - , alert_dispatcher* alert_disp) + , boost::function const& trigger_trim) : m_block_size(block_size) , m_in_use(0) , m_max_use(64) @@ -114,7 +105,6 @@ namespace libtorrent , m_cache_fd(-1) , m_cache_pool(0) #endif - , m_post_alert(alert_disp) #ifndef TORRENT_DISABLE_POOL_ALLOCATOR , m_using_pool_allocator(false) , m_want_pool_allocator(false) @@ -492,7 +482,8 @@ namespace libtorrent return ret; } - void disk_buffer_pool::set_settings(aux::session_settings const& sett) + void disk_buffer_pool::set_settings(aux::session_settings const& sett + , error_code& ec) { mutex::scoped_lock l(m_pool_mutex); @@ -569,11 +560,7 @@ namespace libtorrent m_cache_fd = open(sett.get_str(settings_pack::mmap_cache).c_str(), O_RDWR | O_CREAT | O_EXLOCK | O_TRUNC, 0700); if (m_cache_fd < 0) { - if (m_post_alert) - { - error_code ec(errno, boost::system::generic_category()); - m_ios.post(boost::bind(alert_callback, m_post_alert, new mmap_cache_alert(ec))); - } + ec.assign(errno, boost::system::generic_category()); } else { @@ -585,11 +572,8 @@ namespace libtorrent , MAP_SHARED | MAP_NOCACHE, m_cache_fd, 0); if (intptr_t(m_cache_pool) == -1) { - if (m_post_alert) - { - error_code ec(errno, boost::system::generic_category()); - m_ios.post(boost::bind(alert_callback, m_post_alert, new mmap_cache_alert(ec))); - } + ec.assign(errno, boost::system::generic_category()); + m_cache_pool = 0; // attempt to make MacOS not flush this to disk, making close() // block for a long time diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 8f62fd4aa..466fc1608 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -48,9 +48,9 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/disk_buffer_pool.hpp" #include "libtorrent/disk_io_job.hpp" #include "libtorrent/alert_types.hpp" -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/uncork_interface.hpp" #include "libtorrent/performance_counters.hpp" +#include "libtorrent/alert_manager.hpp" #include "libtorrent/debug.hpp" @@ -155,7 +155,6 @@ namespace libtorrent // ------- disk_io_thread ------ disk_io_thread::disk_io_thread(io_service& ios - , alert_dispatcher* alert_disp , counters& cnt , void* userdata , int block_size) @@ -165,12 +164,11 @@ namespace libtorrent , m_last_cache_expiry(min_time()) , m_last_file_check(clock_type::now()) , m_file_pool(40) - , m_disk_cache(block_size, ios, boost::bind(&disk_io_thread::trigger_cache_trim, this), alert_disp) + , m_disk_cache(block_size, ios, boost::bind(&disk_io_thread::trigger_cache_trim, this)) , m_stats_counters(cnt) , m_ios(ios) , m_work(io_service::work(m_ios)) , m_last_disk_aio_performance_warning(min_time()) - , m_post_alert(alert_disp) , m_outstanding_reclaim_message(false) #if TORRENT_USE_ASSERTS , m_magic(0x1337) @@ -179,7 +177,9 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("disk_io_thread::work"); #endif - m_disk_cache.set_settings(m_settings); + error_code ec; + m_disk_cache.set_settings(m_settings, ec); + TORRENT_ASSERT(!ec); #ifdef TORRENT_DISK_STATS if (g_access_log == NULL) g_access_log = fopen("file_access.log", "a+"); @@ -289,12 +289,17 @@ namespace libtorrent m_blocks_to_reclaim.clear(); } - void disk_io_thread::set_settings(settings_pack* pack) + void disk_io_thread::set_settings(settings_pack* pack, alert_manager& alerts) { TORRENT_ASSERT(m_magic == 0x1337); mutex::scoped_lock l(m_cache_mutex); apply_pack(pack, m_settings); - m_disk_cache.set_settings(m_settings); + error_code ec; + m_disk_cache.set_settings(m_settings, ec); + if (ec && alerts.should_post()) + { + alerts.emplace_alert(ec); + } } // flush all blocks that are below p->hash.offset, since we've diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index 5610261ee..ac988a981 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -283,8 +283,8 @@ namespace libtorrent + (" " + m_parser.message()); if (t->alerts().should_post()) { - t->alerts().post_alert(url_seed_alert(t->get_handle(), url() - , error_msg)); + t->alerts().emplace_alert(t->get_handle(), url() + , error_msg); } received_bytes(0, bytes_transferred); disconnect(error_code(m_parser.status_code(), get_http_category()), op_bittorrent, 1); diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 8f0ad4e6f..298c21fd0 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/kademlia/dht_tracker.hpp" #include "libtorrent/kademlia/msg.hpp" +// TODO: it would be nice to not have a dependency on session here #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/socket.hpp" #include "libtorrent/socket_io.hpp" @@ -138,7 +139,7 @@ namespace libtorrent { namespace dht , rate_limited_udp_socket& sock , dht_settings const& settings, counters& cnt, entry const* state) : m_counters(cnt) - , m_dht(&ses, this, settings, extract_node_id(state) + , m_dht(this, settings, extract_node_id(state) , ses.external_address().external_address(address_v4()), &ses, cnt) , m_sock(sock) , m_last_new_key(aux::time_now() - minutes(int(key_refresh))) diff --git a/src/kademlia/get_peers.cpp b/src/kademlia/get_peers.cpp index 87db5a360..b8672e374 100644 --- a/src/kademlia/get_peers.cpp +++ b/src/kademlia/get_peers.cpp @@ -32,9 +32,9 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include -#include namespace libtorrent { namespace dht { @@ -144,8 +144,10 @@ bool get_peers::invoke(observer_ptr o) a["info_hash"] = m_target.to_string(); if (m_noseeds) a["noseed"] = 1; - m_node.post_alert(new dht_outgoing_get_peers_alert(m_target, m_target - , o->target_ep())); + if (m_node.observer()) + { + m_node.observer()->outgoing_get_peers(m_target, m_target, o->target_ep()); + } m_node.stats_counters().inc_stats_counter(counters::dht_get_peers_out); @@ -244,8 +246,11 @@ bool obfuscated_get_peers::invoke(observer_ptr o) obfuscated_target |= m_target & mask; a["info_hash"] = obfuscated_target.to_string(); - m_node.post_alert(new dht_outgoing_get_peers_alert(m_target - , obfuscated_target, o->target_ep())); + if (m_node.observer()) + { + m_node.observer()->outgoing_get_peers(m_target, obfuscated_target + , o->target_ep()); + } return m_node.m_rpc.invoke(e, o->target_ep(), o); } diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 68f405076..ee6e353fb 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -37,11 +37,11 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/io.hpp" #include "libtorrent/bencode.hpp" #include "libtorrent/hasher.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/alert.hpp" #include "libtorrent/socket.hpp" #include "libtorrent/random.hpp" #include "libtorrent/aux_/session_impl.hpp" +#include "libtorrent/alert_types.hpp" // for dht_lookup + #include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/rpc_manager.hpp" #include "libtorrent/kademlia/routing_table.hpp" @@ -92,8 +92,7 @@ void purge_peers(std::set& peers) void nop() {} -node_impl::node_impl(alert_dispatcher* alert_disp - , udp_socket_interface* sock +node_impl::node_impl(udp_socket_interface* sock , dht_settings const& settings, node_id nid, address const& external_address , dht_observer* observer , struct counters& cnt) @@ -104,7 +103,6 @@ node_impl::node_impl(alert_dispatcher* alert_disp , m_observer(observer) , m_last_tracker_tick(aux::time_now()) , m_last_self_refresh(min_time()) - , m_post_alert(alert_disp) , m_sock(sock) , m_counters(cnt) { @@ -112,14 +110,6 @@ node_impl::node_impl(alert_dispatcher* alert_disp m_secret[1] = random(); } -void node_impl::post_alert(alert* a) -{ - if (!m_post_alert) - delete a; - else - m_post_alert->post_alert(a); -} - bool node_impl::verify_token(std::string const& token, char const* info_hash , udp::endpoint const& addr) { @@ -600,11 +590,8 @@ void node_impl::status(session_status& s) void node_impl::lookup_peers(sha1_hash const& info_hash, entry& reply , bool noseed, bool scrape) const { - if (m_post_alert) - { - alert* a = new dht_get_peers_alert(info_hash); - if (!m_post_alert->post_alert(a)) delete a; - } + if (m_observer) + m_observer->get_peers(info_hash); table_t::const_iterator i = m_map.lower_bound(info_hash); if (i == m_map.end()) return; @@ -954,11 +941,8 @@ void node_impl::incoming_request(msg const& m, entry& e) sha1_hash info_hash(msg_keys[0].string_ptr()); - if (m_post_alert) - { - alert* a = new dht_announce_alert(m.addr.address(), port, info_hash); - if (!m_post_alert->post_alert(a)) delete a; - } + if (m_observer) + m_observer->announce(info_hash, m.addr.address(), port); if (!verify_token(msg_keys[2].string_value(), msg_keys[0].string_ptr(), m.addr)) { diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 4d69c5434..954e0c1d9 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -422,8 +422,8 @@ namespace libtorrent if (t && t->alerts().should_post()) { - t->alerts().post_alert(peer_connect_alert( - t->get_handle(), remote(), pid(), m_socket->type())); + t->alerts().emplace_alert( + t->get_handle(), remote(), pid(), m_socket->type()); } #if defined TORRENT_LOGGING peer_log("*** LOCAL ENDPOINT[ e: %s ]", print_endpoint(m_socket->local_endpoint(ec)).c_str()); @@ -525,8 +525,8 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); if (t) h = t->get_handle(); - m_ses.alerts().post_alert(peer_log_alert( - h, m_remote, m_peer_id, buf)); + m_ses.alerts().emplace_alert( + h, m_remote, m_peer_id, buf); } #endif @@ -2193,8 +2193,8 @@ namespace libtorrent if (t->alerts().should_post()) { - t->alerts().post_alert(invalid_request_alert( - t->get_handle(), m_remote, m_peer_id, r)); + t->alerts().emplace_alert( + t->get_handle(), m_remote, m_peer_id, r); } return; } @@ -2284,8 +2284,8 @@ namespace libtorrent if (t->alerts().should_post()) { - t->alerts().post_alert(invalid_request_alert( - t->get_handle(), m_remote, m_peer_id, r)); + t->alerts().emplace_alert( + t->get_handle(), m_remote, m_peer_id, r); } // every ten invalid request, remind the peer that it's choked @@ -2463,8 +2463,8 @@ namespace libtorrent { if (t->alerts().should_post()) { - t->alerts().post_alert(unwanted_block_alert(t->get_handle(), m_remote - , m_peer_id, b.block_index, b.piece_index)); + t->alerts().emplace_alert(t->get_handle() + , m_remote, m_peer_id, int(b.block_index), int(b.piece_index)); } #if defined TORRENT_LOGGING peer_log("*** The block we just got was not in the request queue ***"); @@ -2603,8 +2603,8 @@ namespace libtorrent { if (t->alerts().should_post()) { - t->alerts().post_alert(peer_error_alert(t->get_handle(), m_remote - , m_peer_id, op_bittorrent, errors::peer_sent_empty_piece)); + t->alerts().emplace_alert(t->get_handle(), m_remote + , m_peer_id, op_bittorrent, errors::peer_sent_empty_piece); } // This is used as a reject-request by bitcomet incoming_reject_request(p); @@ -2648,8 +2648,9 @@ namespace libtorrent { if (t->alerts().should_post()) { - t->alerts().post_alert(unwanted_block_alert(t->get_handle(), m_remote - , m_peer_id, block_finished.block_index, block_finished.piece_index)); + t->alerts().emplace_alert(t->get_handle() + , m_remote, m_peer_id, int(block_finished.block_index) + , int(block_finished.piece_index)); } #if defined TORRENT_LOGGING peer_log("*** The block we just got was not in the request queue ***"); @@ -2720,8 +2721,8 @@ namespace libtorrent m_snubbed = false; if (t->alerts().should_post()) { - t->alerts().post_alert(peer_unsnubbed_alert(t->get_handle() - , m_remote, m_peer_id)); + t->alerts().emplace_alert(t->get_handle() + , m_remote, m_peer_id); } } @@ -2759,8 +2760,8 @@ namespace libtorrent && m_settings.get_int(settings_pack::cache_size) > 5 && t->alerts().should_post()) { - t->alerts().post_alert(performance_alert(t->get_handle() - , performance_alert::too_high_disk_queue_limit)); + t->alerts().emplace_alert(t->get_handle() + , performance_alert::too_high_disk_queue_limit); } m_request_time.add_sample(total_milliseconds(now - m_requested)); @@ -2923,8 +2924,9 @@ namespace libtorrent if (t->alerts().should_post()) { - t->alerts().post_alert(block_finished_alert(t->get_handle(), - remote(), pid(), block_finished.block_index, block_finished.piece_index)); + t->alerts().emplace_alert(t->get_handle(), + remote(), pid(), int(block_finished.block_index) + , int(block_finished.piece_index)); } disconnect_if_redundant(); @@ -3358,8 +3360,8 @@ namespace libtorrent if (t->alerts().should_post()) { - t->alerts().post_alert(block_downloading_alert(t->get_handle(), - remote(), pid(), block.block_index, block.piece_index)); + t->alerts().emplace_alert(t->get_handle(), + remote(), pid(), block.block_index, block.piece_index); } pending_block pb(block); @@ -4079,8 +4081,8 @@ namespace libtorrent && t) { if (t->alerts().should_post()) - t->alerts().post_alert(performance_alert( - handle, performance_alert::too_few_outgoing_ports)); + t->alerts().emplace_alert( + handle, performance_alert::too_few_outgoing_ports); } if (t) @@ -4090,15 +4092,14 @@ namespace libtorrent if ((error > 1 || ec.category() == get_socks_category()) && t->alerts().should_post()) { - t->alerts().post_alert( - peer_error_alert(handle, remote(), pid(), op, ec)); + t->alerts().emplace_alert(handle, remote() + , pid(), op, ec); } if (error <= 1 && t->alerts().should_post()) { - t->alerts().post_alert( - peer_disconnected_alert(handle, remote(), pid(), op - , m_socket->type(), ec, close_reason)); + t->alerts().emplace_alert(handle + , remote(), pid(), op, m_socket->type(), ec, close_reason); } } @@ -4509,10 +4510,10 @@ namespace libtorrent for (int channel = 0; channel < 2; ++channel) { if ((warning & (1 << channel)) == 0) continue; - t->alerts().post_alert(performance_alert(t->get_handle() + t->alerts().emplace_alert(t->get_handle() , channel == peer_connection::download_channel ? performance_alert::download_limit_too_low - : performance_alert::upload_limit_too_low)); + : performance_alert::upload_limit_too_low); } } @@ -4713,8 +4714,8 @@ namespace libtorrent if (m_desired_queue_size == m_max_out_request_queue && t->alerts().should_post()) { - t->alerts().post_alert(performance_alert(t->get_handle() - , performance_alert::outstanding_request_limit_reached)); + t->alerts().emplace_alert(t->get_handle() + , performance_alert::outstanding_request_limit_reached); } int piece_timeout = m_settings.get_int(settings_pack::piece_timeout); @@ -4768,8 +4769,8 @@ namespace libtorrent m_snubbed = true; if (t->alerts().should_post()) { - t->alerts().post_alert(peer_snubbed_alert(t->get_handle() - , m_remote, m_peer_id)); + t->alerts().emplace_alert(t->get_handle() + , m_remote, m_peer_id); } } m_desired_queue_size = 1; @@ -4824,8 +4825,9 @@ namespace libtorrent if (t->alerts().should_post()) { - t->alerts().post_alert(block_timeout_alert(t->get_handle() - , remote(), pid(), qe.block.block_index, qe.block.piece_index)); + t->alerts().emplace_alert(t->get_handle() + , remote(), pid(), int(qe.block.block_index) + , int(qe.block.piece_index)); } // request a new block before removing the previous @@ -5089,9 +5091,9 @@ namespace libtorrent write_dont_have(r.piece); write_reject_request(r); if (t->alerts().should_post()) - t->alerts().post_alert(file_error_alert(j->error.ec + t->alerts().emplace_alert(j->error.ec , t->resolve_filename(j->error.file) - , j->error.operation_str(), t->get_handle())); + , j->error.operation_str(), t->get_handle()); ++m_disk_read_failures; if (m_disk_read_failures > 100) disconnect(j->error.ec, op_file_read); @@ -5343,8 +5345,8 @@ namespace libtorrent // peer to hang on to the disk if (t && t->alerts().should_post()) { - t->alerts().post_alert(performance_alert(t->get_handle() - , performance_alert::send_buffer_watermark_too_low)); + t->alerts().emplace_alert(t->get_handle() + , performance_alert::send_buffer_watermark_too_low); } } } diff --git a/src/rss.cpp b/src/rss.cpp index cdbafed63..c59566ef0 100644 --- a/src/rss.cpp +++ b/src/rss.cpp @@ -344,8 +344,8 @@ void feed::on_feed(error_code const& ec m_error = ec; if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url - , rss_alert::state_error, m_error)); + m_ses.m_alerts.emplace_alert(my_handle(), m_settings.url + , rss_alert::state_error, m_error); } return; } @@ -356,8 +356,8 @@ void feed::on_feed(error_code const& ec m_error = error_code(parser.status_code(), get_http_category()); if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url - , rss_alert::state_error, m_error)); + m_ses.m_alerts.emplace_alert(my_handle(), m_settings.url + , rss_alert::state_error, m_error); } return; } @@ -391,8 +391,8 @@ void feed::on_feed(error_code const& ec // report that we successfully updated the feed if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url - , rss_alert::state_updated, error_code())); + m_ses.m_alerts.emplace_alert(my_handle(), m_settings.url + , rss_alert::state_updated, error_code()); } // update m_ses.m_next_rss_update timestamps @@ -541,7 +541,7 @@ void feed::add_item(feed_item const& item) i.handle = torrent_handle(m_ses.find_torrent(i.uuid.empty() ? i.url : i.uuid)); if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(rss_item_alert(my_handle(), i)); + m_ses.m_alerts.emplace_alert(my_handle(), i); if (m_settings.auto_download) { @@ -581,8 +581,8 @@ int feed::update_feed() if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url - , rss_alert::state_updating, error_code())); + m_ses.m_alerts.emplace_alert(my_handle(), m_settings.url + , rss_alert::state_updating, error_code()); } boost::shared_ptr feed( diff --git a/src/session.cpp b/src/session.cpp index 0a4122726..135cb059a 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -1134,33 +1134,42 @@ namespace libtorrent { return TORRENT_SYNC_CALL_RET(int, num_connections); } -#endif // TORRENT_NO_DEPRECATE void session::set_alert_dispatch(boost::function)> const& fun) { - TORRENT_ASYNC_CALL1(set_alert_dispatch, fun); + m_impl->m_alerts.set_dispatch_function(fun); } +#endif // TORRENT_NO_DEPRECATE - std::auto_ptr session::pop_alert() - { - return m_impl->pop_alert(); - } - - void session::pop_alerts(std::deque* alerts) - { - for (std::deque::iterator i = alerts->begin() - , end(alerts->end()); i != end; ++i) - delete *i; - alerts->clear(); - m_impl->pop_alerts(alerts); - } - - alert const* session::wait_for_alert(time_duration max_wait) + alert* session::wait_for_alert(time_duration max_wait) { return m_impl->wait_for_alert(max_wait); } + // the alerts are const, they may not be deleted by the client + void session::pop_alerts(std::vector* alerts) + { + m_impl->pop_alerts(alerts); + } + + void session::set_alert_notify(boost::function const& fun) + { + m_impl->m_alerts.set_notify_function(fun); + } + #ifndef TORRENT_NO_DEPRECATE + void session::pop_alerts(std::deque* alerts) + { + m_impl->pop_alerts(alerts); + } + + std::auto_ptr session::pop_alert() + { + alert const* a = m_impl->pop_alert(); + if (a == NULL) return std::auto_ptr(); + return a->clone(); + } + void session::set_alert_mask(boost::uint32_t m) { settings_pack p; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 3230f7f15..c2c26fd83 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -348,7 +348,10 @@ namespace aux { , m_ssl_ctx(m_io_service, asio::ssl::context::sslv23) #endif , m_alerts(m_settings.get_int(settings_pack::alert_queue_size), alert::all_categories) - , m_disk_thread(m_io_service, this, m_stats_counters +#ifndef TORRENT_NO_DEPRECATE + , m_alert_pointer_pos(0) +#endif + , m_disk_thread(m_io_service, m_stats_counters , (uncork_interface*)this) , m_download_rate(peer_connection::download_channel) #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT @@ -516,9 +519,9 @@ namespace aux { #if defined TORRENT_LOGGING - session_log("libtorrent configuration: %s\n" - "libtorrent version: %s\n" - "libtorrent revision: %s\n\n" + session_log("config: %s\n" + "version: %s\n" + "revision: %s\n\n" , TORRENT_CFG_STRING , LIBTORRENT_VERSION , LIBTORRENT_REVISION); @@ -1520,7 +1523,7 @@ namespace aux { != m_settings.get_str(settings_pack::listen_interfaces)); apply_pack(pack, m_settings, this); - m_disk_thread.set_settings(pack); + m_disk_thread.set_settings(pack, m_alerts); delete pack; if (reopen_listen_port) @@ -1574,7 +1577,7 @@ namespace aux { if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(device, last_op, ec, sock_type)); + m_alerts.emplace_alert(device, last_op, ec, sock_type); #if defined TORRENT_LOGGING session_log("failed to open socket: %s: %s" @@ -1645,7 +1648,7 @@ namespace aux { { // not even that worked, give up if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(device, last_op, ec, sock_type)); + m_alerts.emplace_alert(device, last_op, ec, sock_type); #if defined TORRENT_LOGGING session_log("cannot bind to interface \"%s\": %s" , device.c_str(), ec.message().c_str()); @@ -1663,7 +1666,7 @@ namespace aux { if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(device, last_op, ec, sock_type)); + m_alerts.emplace_alert(device, last_op, ec, sock_type); #if defined TORRENT_LOGGING session_log("cannot listen on interface \"%s\": %s" , device.c_str(), ec.message().c_str()); @@ -1680,7 +1683,7 @@ namespace aux { if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(device, last_op, ec, sock_type)); + m_alerts.emplace_alert(device, last_op, ec, sock_type); #if defined TORRENT_LOGGING session_log("failed to get peer name \"%s\": %s" , device.c_str(), ec.message().c_str()); @@ -1690,9 +1693,9 @@ namespace aux { } if (m_alerts.should_post()) - m_alerts.post_alert(listen_succeeded_alert(tcp::endpoint(bind_ip, port) + m_alerts.emplace_alert(tcp::endpoint(bind_ip, port) , (flags & open_ssl_socket) ? listen_succeeded_alert::tcp_ssl - : listen_succeeded_alert::tcp)); + : listen_succeeded_alert::tcp); #if defined TORRENT_LOGGING session_log(" listening on: %s external port: %d" @@ -1886,10 +1889,10 @@ retry: { // only report this if both IPv4 and IPv6 fails for a device if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(device + m_alerts.emplace_alert(device , listen_failed_alert::bind , error_code(boost::system::errc::no_such_device, generic_category()) - , listen_failed_alert::tcp)); + , listen_failed_alert::tcp); } } } @@ -1907,8 +1910,8 @@ retry: goto retry; } if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert(print_endpoint(m_listen_interface) - , listen_failed_alert::bind, ec, listen_failed_alert::udp)); + m_alerts.emplace_alert(print_endpoint(m_listen_interface) + , listen_failed_alert::bind, ec, listen_failed_alert::udp); return; } @@ -1931,17 +1934,17 @@ retry: if (m_alerts.should_post()) { error_code err; - m_alerts.post_alert(listen_failed_alert(print_endpoint(ssl_bind_if) - , listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl)); + m_alerts.emplace_alert(print_endpoint(ssl_bind_if) + , listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); } ec.clear(); } else { if (m_alerts.should_post()) - m_alerts.post_alert(listen_succeeded_alert( + m_alerts.emplace_alert( tcp::endpoint(ssl_bind_if.address(), ssl_bind_if.port()) - , listen_succeeded_alert::utp_ssl)); + , listen_succeeded_alert::utp_ssl); } } #endif // TORRENT_USE_OPENSSL @@ -1963,8 +1966,8 @@ retry: if (m_alerts.should_post()) { error_code err; - m_alerts.post_alert(listen_failed_alert(print_endpoint(m_listen_interface) - , listen_failed_alert::bind, ec, listen_failed_alert::udp)); + m_alerts.emplace_alert(print_endpoint(m_listen_interface) + , listen_failed_alert::bind, ec, listen_failed_alert::udp); } return; } @@ -1974,7 +1977,7 @@ retry: maybe_update_udp_mapping(0, m_listen_interface.port(), m_listen_interface.port()); maybe_update_udp_mapping(1, m_listen_interface.port(), m_listen_interface.port()); if (m_alerts.should_post()) - m_alerts.post_alert(listen_succeeded_alert(m_listen_interface, listen_succeeded_alert::udp)); + m_alerts.emplace_alert(m_listen_interface, listen_succeeded_alert::udp); } if (m_settings.get_int(settings_pack::peer_tos) != 0) @@ -1988,7 +1991,7 @@ retry: if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(udp_error_alert(udp::endpoint(), ec)); + m_alerts.emplace_alert(udp::endpoint(), ec); } // initiate accepting on the listen sockets @@ -2095,7 +2098,7 @@ retry: if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(i2p_alert(ec)); + m_alerts.emplace_alert(ec); #if defined TORRENT_LOGGING session_log("i2p open failed (%d) %s", ec.value(), ec.message().c_str()); @@ -2140,8 +2143,8 @@ retry: if (e) { if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert("i2p", listen_failed_alert::accept - , e, listen_failed_alert::i2p)); + m_alerts.emplace_alert("i2p", listen_failed_alert::accept + , e, listen_failed_alert::i2p); #if defined TORRENT_LOGGING session_log("cannot bind to port %d: %s" , m_listen_interface.port(), e.message().c_str()); @@ -2163,7 +2166,7 @@ retry: // don't bubble up operation aborted errors to the user if (ec != asio::error::operation_aborted && m_alerts.should_post()) - m_alerts.post_alert(udp_error_alert(ep, ec)); + m_alerts.emplace_alert(ep, ec); #if defined TORRENT_LOGGING session_log("UDP socket error: (%d) %s", ec.value(), ec.message().c_str()); @@ -2263,8 +2266,8 @@ retry: , boost::bind(&torrent_map::value_type::second, _1))); if (m_alerts.should_post()) - m_alerts.post_alert(performance_alert( - torrent_handle(), performance_alert::too_few_file_descriptors)); + m_alerts.emplace_alert( + torrent_handle(), performance_alert::too_few_file_descriptors); if (i != m_torrents.end()) { @@ -2279,8 +2282,8 @@ retry: if (m_alerts.should_post()) { error_code err; - m_alerts.post_alert(listen_failed_alert(print_endpoint(ep), listen_failed_alert::accept, e - , ssl ? listen_failed_alert::tcp_ssl : listen_failed_alert::tcp)); + m_alerts.emplace_alert(print_endpoint(ep), listen_failed_alert::accept, e + , ssl ? listen_failed_alert::tcp_ssl : listen_failed_alert::tcp); } return; } @@ -2351,8 +2354,8 @@ retry: { if (m_alerts.should_post()) { - m_alerts.post_alert(peer_error_alert(torrent_handle(), endp - , peer_id(), op_ssl_handshake, ec)); + m_alerts.emplace_alert(torrent_handle(), endp + , peer_id(), op_ssl_handshake, ec); } return; } @@ -2407,8 +2410,8 @@ retry: session_log(" rejected uTP connection"); #endif if (m_alerts.should_post()) - m_alerts.post_alert(peer_blocked_alert(torrent_handle() - , endp.address(), peer_blocked_alert::utp_disabled)); + m_alerts.emplace_alert(torrent_handle() + , endp.address(), peer_blocked_alert::utp_disabled); return; } @@ -2419,8 +2422,8 @@ retry: session_log(" rejected TCP connection"); #endif if (m_alerts.should_post()) - m_alerts.post_alert(peer_blocked_alert(torrent_handle() - , endp.address(), peer_blocked_alert::tcp_disabled)); + m_alerts.emplace_alert(torrent_handle() + , endp.address(), peer_blocked_alert::tcp_disabled); return; } @@ -2455,8 +2458,8 @@ retry: , local.address().to_string(ec).c_str()); #endif if (m_alerts.should_post()) - m_alerts.post_alert(peer_blocked_alert(torrent_handle() - , endp.address(), peer_blocked_alert::invalid_local_interface)); + m_alerts.emplace_alert(torrent_handle() + , endp.address(), peer_blocked_alert::invalid_local_interface); return; } } @@ -2478,8 +2481,8 @@ retry: session_log("filtered blocked ip"); #endif if (m_alerts.should_post()) - m_alerts.post_alert(peer_blocked_alert(torrent_handle() - , endp.address(), peer_blocked_alert::ip_filter)); + m_alerts.emplace_alert(torrent_handle() + , endp.address(), peer_blocked_alert::ip_filter); return; } @@ -2518,11 +2521,10 @@ retry: { if (m_alerts.should_post()) { - m_alerts.post_alert( - peer_disconnected_alert(torrent_handle(), endp, peer_id() + m_alerts.emplace_alert(torrent_handle(), endp, peer_id() , op_bittorrent, s->type() , error_code(errors::too_many_connections, get_libtorrent_category()) - , close_no_reason)); + , close_no_reason); } #if defined TORRENT_LOGGING session_log("number of connections limit exceeded (conns: %d, limit: %d, slack: %d), connection rejected" @@ -2561,7 +2563,7 @@ retry: m_stats_counters.inc_stats_counter(counters::incoming_connections); if (m_alerts.should_post()) - m_alerts.post_alert(incoming_connection_alert(s->type(), endp)); + m_alerts.emplace_alert(s->type(), endp); setup_socket_buffers(*s); @@ -2615,8 +2617,8 @@ retry: if (e) { if (m_alerts.should_post()) - m_alerts.post_alert(listen_failed_alert("socks5", listen_failed_alert::accept, e - , listen_failed_alert::socks5)); + m_alerts.emplace_alert("socks5", listen_failed_alert::accept, e + , listen_failed_alert::socks5); return; } open_new_incoming_socks_connection(); @@ -2662,14 +2664,6 @@ retry: if (i != m_connections.end()) m_connections.erase(i); } - // implements alert_dispatcher - bool session_impl::post_alert(alert* a) - { - if (!m_alerts.should_post(a)) return false; - m_alerts.post_alert_ptr(a); - return true; - } - void session_impl::set_peer_id(peer_id const& id) { m_peer_id = id; @@ -3033,16 +3027,16 @@ retry: && m_stat.download_ip_overhead() >= down_limit && m_alerts.should_post()) { - m_alerts.post_alert(performance_alert(torrent_handle() - , performance_alert::download_limit_too_low)); + m_alerts.emplace_alert(torrent_handle() + , performance_alert::download_limit_too_low); } if (up_limit > 0 && m_stat.upload_ip_overhead() >= up_limit && m_alerts.should_post()) { - m_alerts.post_alert(performance_alert(torrent_handle() - , performance_alert::upload_limit_too_low)); + m_alerts.emplace_alert(torrent_handle() + , performance_alert::upload_limit_too_low); } } @@ -3921,8 +3915,8 @@ retry: // assume 20 kB/s max_upload_rate = (std::max)(20000, m_peak_up_rate + 10000); if (m_alerts.should_post()) - m_alerts.post_alert(performance_alert(torrent_handle() - , performance_alert::bittyrant_with_no_uplimit)); + m_alerts.emplace_alert(torrent_handle() + , performance_alert::bittyrant_with_no_uplimit); } int allowed_upload_slots = unchoke_sort(peers, max_upload_rate @@ -4298,7 +4292,7 @@ retry: char buf[1024]; vsnprintf(buf, sizeof(buf), fmt, v); - m_alerts.post_alert(log_alert(buf)); + m_alerts.emplace_alert(buf); } void session_impl::log_all_torrents(peer_connection* p) @@ -4345,31 +4339,33 @@ retry: TORRENT_ASSERT(is_single_thread()); - std::auto_ptr alert(new state_update_alert()); std::vector& state_updates = m_torrent_lists[aux::session_impl::torrent_state_updates]; - alert->status.reserve(state_updates.size()); - #if TORRENT_USE_ASSERTS m_posting_torrent_updates = true; #endif + std::vector status; + status.reserve(state_updates.size()); + // TODO: it might be a nice feature here to limit the number of torrents // to send in a single update. By just posting the first n torrents, they // would nicely be round-robined because the torrent lists are always - // pushed back + // pushed back. Perhaps the status_update_alert could even have a fixed + // array of n entries rather than a vector, to further improve memory + // locality. for (std::vector::iterator i = state_updates.begin() , end(state_updates.end()); i != end; ++i) { torrent* t = *i; TORRENT_ASSERT(t->m_links[aux::session_impl::torrent_state_updates].in_list()); - alert->status.push_back(torrent_status()); + status.push_back(torrent_status()); // querying accurate download counters may require // the torrent to be loaded. Loading a torrent, and evicting another // one will lead to calling state_updated(), which screws with // this list while we're working on it, and break things - t->status(&alert->status.back(), flags); + t->status(&status.back(), flags); t->clear_in_state_update(); } state_updates.clear(); @@ -4378,15 +4374,11 @@ retry: m_posting_torrent_updates = false; #endif - m_alerts.post_alert_ptr(alert.release()); + m_alerts.emplace_alert(status); } void session_impl::post_session_stats() { - std::auto_ptr alert(new session_stats_alert()); - std::vector& values = alert->values; - values.resize(counters::num_counters, 0); - m_disk_thread.update_stats_counters(m_stats_counters); m_stats_counters.set_value(counters::sent_ip_overhead_bytes @@ -4405,24 +4397,20 @@ retry: m_stats_counters.set_value(counters::limiter_down_bytes , m_download_rate.queued_bytes()); - for (int i = 0; i < counters::num_counters; ++i) - values[i] = m_stats_counters[i]; - - alert->timestamp = total_microseconds(clock_type::now() - m_created); - - m_alerts.post_alert_ptr(alert.release()); + m_alerts.emplace_alert(m_stats_counters); } void session_impl::post_dht_stats() { - std::auto_ptr alert(new dht_stats_alert()); - + std::vector requests; + std::vector table; + #ifndef TORRENT_DISABLE_DHT if (m_dht) - m_dht->dht_status(alert->routing_table, alert->active_requests); + m_dht->dht_status(table, requests); #endif - m_alerts.post_alert_ptr(alert.release()); + m_alerts.emplace_alert(table, requests); } std::vector session_impl::get_torrents() const @@ -4466,7 +4454,7 @@ retry: if (j->error.ec) { ec = j->error.ec; - m_alerts.post_alert(add_torrent_alert(handle, *params, ec)); + m_alerts.emplace_alert(handle, *params, ec); } else { @@ -4495,7 +4483,7 @@ retry: , error_code& ec) { torrent_handle h = add_torrent_impl(p, ec); - m_alerts.post_alert(add_torrent_alert(h, p, ec)); + m_alerts.emplace_alert(h, p, ec); return h; } @@ -4747,7 +4735,7 @@ retry: ? params.url : params.uuid, torrent_ptr)); if (m_alerts.should_post()) - m_alerts.post_alert(torrent_added_alert(torrent_ptr->get_handle())); + m_alerts.emplace_alert(torrent_ptr->get_handle()); // recalculate auto-managed torrents sooner (or put it off) // if another torrent will be added within one second from now @@ -4861,7 +4849,7 @@ retry: boost::shared_ptr tptr = h.m_torrent.lock(); if (!tptr) return; - m_alerts.post_alert(torrent_removed_alert(tptr->get_handle(), tptr->info_hash())); + m_alerts.emplace_alert(tptr->get_handle(), tptr->info_hash()); remove_torrent_impl(tptr, options); @@ -4898,8 +4886,8 @@ retry: if (!t.delete_files()) { if (m_alerts.should_post()) - m_alerts.post_alert(torrent_delete_failed_alert(t.get_handle() - , error_code(), t.torrent_file().info_hash())); + m_alerts.emplace_alert(t.get_handle() + , error_code(), t.torrent_file().info_hash()); } } @@ -5206,7 +5194,7 @@ retry: t->do_connect_boost(); if (m_alerts.should_post()) - m_alerts.post_alert(lsd_peer_alert(t->get_handle(), peer)); + m_alerts.emplace_alert(t->get_handle(), peer); } void session_impl::on_port_map_log( @@ -5215,7 +5203,7 @@ retry: TORRENT_ASSERT(map_transport >= 0 && map_transport <= 1); // log message if (m_alerts.should_post()) - m_alerts.post_alert(portmap_log_alert(map_transport, msg)); + m_alerts.emplace_alert(map_transport, msg); } void session_impl::on_port_mapping(int mapping, address const& ip, int port @@ -5229,8 +5217,8 @@ retry: { m_external_udp_port = port; if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); + m_alerts.emplace_alert(mapping, port + , map_transport); return; } @@ -5248,22 +5236,22 @@ retry: m_listen_sockets.front().external_port = port; } if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); + m_alerts.emplace_alert(mapping, port + , map_transport); return; } if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(portmap_error_alert(mapping - , map_transport, ec)); + m_alerts.emplace_alert(mapping + , map_transport, ec); } else { if (m_alerts.should_post()) - m_alerts.post_alert(portmap_alert(mapping, port - , map_transport)); + m_alerts.emplace_alert(mapping, port + , map_transport); } } @@ -5402,7 +5390,7 @@ retry: void on_bootstrap(alert_manager& alerts) { if (alerts.should_post()) - alerts.post_alert(dht_bootstrap_alert()); + alerts.emplace_alert(); } void session_impl::start_dht(entry const& startup_state) @@ -5470,8 +5458,8 @@ retry: if (e) { if (m_alerts.should_post()) - m_alerts.post_alert(dht_error_alert( - dht_error_alert::hostname_lookup, e)); + m_alerts.emplace_alert( + dht_error_alert::hostname_lookup, e); return; } @@ -5491,7 +5479,7 @@ retry: , dht::item const& i) { TORRENT_ASSERT(!i.is_mutable()); - m_alerts.post_alert(dht_immutable_item_alert(target, i.value())); + m_alerts.emplace_alert(target, i.value()); } void session_impl::dht_get_immutable_item(sha1_hash const& target) @@ -5505,8 +5493,8 @@ retry: void session_impl::get_mutable_callback(dht::item const& i) { TORRENT_ASSERT(i.is_mutable()); - m_alerts.post_alert(dht_mutable_item_alert(i.pk(), i.sig(), i.seq() - , i.salt(), i.value())); + m_alerts.emplace_alert(i.pk(), i.sig(), i.seq() + , i.salt(), i.value()); } // key is a 32-byte binary string, the public key to look up. @@ -5522,7 +5510,7 @@ retry: void on_dht_put(alert_manager& alerts, sha1_hash target) { if (alerts.should_post()) - alerts.post_alert(dht_put_alert(target)); + alerts.emplace_alert(target); } void session_impl::dht_put_item(entry data, sha1_hash target) @@ -5545,7 +5533,7 @@ retry: i.assign(value, salt, seq, pk.data(), sig.data()); if (alerts.should_post()) - alerts.post_alert(dht_put_alert(pk, sig, salt, seq)); + alerts.emplace_alert(pk, sig, salt, seq); } void session_impl::dht_put_mutable_item(boost::array key @@ -5810,8 +5798,8 @@ retry: >= allowed_upload_slots / 2) { if (m_alerts.should_post()) - m_alerts.post_alert(performance_alert(torrent_handle() - , performance_alert::too_many_optimistic_unchoke_slots)); + m_alerts.emplace_alert(torrent_handle() + , performance_alert::too_many_optimistic_unchoke_slots); } } @@ -5829,8 +5817,8 @@ retry: && cache_size > 5 && m_alerts.should_post()) { - m_alerts.post_alert(performance_alert(torrent_handle() - , performance_alert::too_high_disk_queue_limit)); + m_alerts.emplace_alert(torrent_handle() + , performance_alert::too_high_disk_queue_limit); } } @@ -5961,7 +5949,7 @@ retry: if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(udp_error_alert(udp::endpoint(), ec)); + m_alerts.emplace_alert(udp::endpoint(), ec); } #ifdef TORRENT_USE_OPENSSL @@ -5969,7 +5957,7 @@ retry: if (ec) { if (m_alerts.should_post()) - m_alerts.post_alert(udp_error_alert(udp::endpoint(), ec)); + m_alerts.emplace_alert(udp::endpoint(), ec); } #endif } @@ -6163,6 +6151,24 @@ retry: } } + void session_impl::update_alert_mask() + { + m_alerts.set_alert_mask(m_settings.get_int(settings_pack::alert_mask)); + } + + void session_impl::pop_alerts(std::vector* alerts) + { + int num_resume = 0; + m_alerts.get_all(*alerts, num_resume); + if (num_resume > 0) + { + // we can only issue more resume data jobs from + // the network thread + m_io_service.post(boost::bind(&session_impl::async_resume_dispatched + , this, num_resume)); + } + } + #ifndef TORRENT_NO_DEPRECATE void session_impl::update_rate_limit_utp() { @@ -6194,49 +6200,62 @@ retry: void session_impl::update_ignore_rate_limits_on_local_network() { - init_peer_class_filter(m_settings.get_bool(settings_pack::ignore_limits_on_local_network)); + init_peer_class_filter( + m_settings.get_bool(settings_pack::ignore_limits_on_local_network)); + } + + // this function is called on the user's thread + // not the network thread + void session_impl::pop_alerts() + { + // if we don't have any alerts in our local cache, we have to ask + // the alert_manager for more. It will swap our vector with its and + // destruct eny left-over alerts in there. + if (m_alert_pointer_pos >= m_alert_pointers.size()) + { + pop_alerts(&m_alert_pointers); + m_alert_pointer_pos = 0; + } + } + + alert const* session_impl::pop_alert() + { + if (m_alert_pointer_pos >= m_alert_pointers.size()) + { + pop_alerts(); + if (m_alert_pointers.empty()) + return NULL; + } + + if (m_alert_pointers.empty()) return NULL; + + // clone here to be backwards compatible, to make the client delete the + // alert object + return m_alert_pointers[m_alert_pointer_pos++]; + } + + + void session_impl::pop_alerts(std::deque* alerts) + { + alerts->clear(); + if (m_alert_pointer_pos >= m_alert_pointers.size()) + { + pop_alerts(); + if (m_alert_pointers.empty()) + return; + } + + for (std::vector::iterator i = m_alert_pointers.begin() + + m_alert_pointer_pos, end(m_alert_pointers.end()); + i != end; ++i) + { + alerts->push_back((*i)->clone().release()); + } + m_alert_pointer_pos = m_alert_pointers.size(); } #endif - void session_impl::update_alert_mask() - { - m_alerts.set_alert_mask(m_settings.get_int(settings_pack::alert_mask)); - } - - void session_impl::set_alert_dispatch(boost::function)> const& fun) - { - m_alerts.set_dispatch_function(fun); - } - - // this function is called on the user's thread - // not the network thread - std::auto_ptr session_impl::pop_alert() - { - int num_resume = 0; - std::auto_ptr ret = m_alerts.get(num_resume); - if (num_resume > 0) - { - // we can only issue more resume data jobs from - // the network thread - m_io_service.post(boost::bind(&session_impl::async_resume_dispatched - , this, num_resume)); - } - return ret; - } - - // this function is called on the user's thread - // not the network thread - void session_impl::pop_alerts(std::deque* alerts) - { - int num_resume = 0; - m_alerts.get_all(alerts, num_resume); - // we can only issue more resume data jobs from - // the network thread - m_io_service.post(boost::bind(&session_impl::async_resume_dispatched - , this, num_resume)); - } - - alert const* session_impl::wait_for_alert(time_duration max_wait) + alert* session_impl::wait_for_alert(time_duration max_wait) { return m_alerts.wait_for_alert(max_wait); } @@ -6264,14 +6283,14 @@ retry: error_code ec; m_lsd->start(ec); if (ec && m_alerts.should_post()) - m_alerts.post_alert(lsd_error_alert(ec)); + m_alerts.emplace_alert(ec); } #if defined TORRENT_LOGGING void session_impl::on_lsd_log(char const* log) { if (!m_alerts.should_post()) return; - m_alerts.post_alert(log_alert(log)); + m_alerts.emplace_alert(log); } #endif @@ -6414,6 +6433,26 @@ retry: set_external_address(ip, source_dht, source); } + void session_impl::get_peers(sha1_hash const& ih) + { + if (!m_alerts.should_post()) return; + m_alerts.emplace_alert(ih); + } + + void session_impl::announce(sha1_hash const& ih, address const& addr + , int port) + { + if (!m_alerts.should_post()) return; + m_alerts.emplace_alert(addr, port, ih); + } + + void session_impl::outgoing_get_peers(sha1_hash const& target + , sha1_hash const& sent_target, udp::endpoint const& ep) + { + if (!m_alerts.should_post()) return; + m_alerts.emplace_alert(target, sent_target, ep); + } + void session_impl::set_external_address(address const& ip , int source_type, address const& source) { @@ -6429,7 +6468,7 @@ retry: #endif if (m_alerts.should_post()) - m_alerts.post_alert(external_ip_alert(ip)); + m_alerts.emplace_alert(ip); for (torrent_map::iterator i = m_torrents.begin() , end(m_torrents.end()); i != end; ++i) diff --git a/src/torrent.cpp b/src/torrent.cpp index 531d5fa49..480e9397c 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -546,8 +546,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(metadata_received_alert( - get_handle())); + m_ses.alerts().emplace_alert( + get_handle()); } state_updated(); @@ -635,7 +635,7 @@ namespace libtorrent m_ses.remove_torrent_impl(me, 0); if (alerts().should_post()) - alerts().post_alert(torrent_update_alert(get_handle(), info_hash(), tf->info_hash())); + alerts().emplace_alert(get_handle(), info_hash(), tf->info_hash()); m_torrent_file = tf; m_info_hash = tf->info_hash(); @@ -693,8 +693,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(metadata_received_alert( - get_handle())); + m_ses.alerts().emplace_alert( + get_handle()); } state_updated(); @@ -772,7 +772,7 @@ namespace libtorrent debug_log("resume data rejected: %s pos: %d", ec.message().c_str(), pos); #endif if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(fastresume_rejected_alert(get_handle(), ec, "", 0)); + m_ses.alerts().emplace_alert(get_handle(), ec, "", (char const*)0); } } @@ -911,8 +911,8 @@ namespace libtorrent if (m_abort || m_deleted) { // failed - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category()))); + m_ses.alerts().emplace_alert( + get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category())); return; } @@ -936,8 +936,8 @@ namespace libtorrent if (!need_loaded()) { rp->piece_data.reset(); - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), r.piece, rp->piece_data, 0)); + m_ses.alerts().emplace_alert( + get_handle(), r.piece, rp->piece_data, 0); delete rp; return; } @@ -1125,8 +1125,8 @@ namespace libtorrent if (j->error.ec == error_code(boost::system::errc::not_enough_memory, generic_category())) { if (alerts().should_post()) - alerts().post_alert(file_error_alert(j->error.ec - , resolve_filename(j->error.file), j->error.operation_str(), get_handle())); + alerts().emplace_alert(j->error.ec + , resolve_filename(j->error.file), j->error.operation_str(), get_handle()); if (c) c->disconnect(errors::no_memory, op_file); return; } @@ -1135,8 +1135,8 @@ namespace libtorrent // notify the user of the error if (alerts().should_post()) - alerts().post_alert(file_error_alert(j->error.ec - , resolve_filename(j->error.file), j->error.operation_str(), get_handle())); + alerts().emplace_alert(j->error.ec + , resolve_filename(j->error.file), j->error.operation_str(), get_handle()); // put the torrent in an error-state set_error(j->error.ec, j->error.file); @@ -1220,13 +1220,13 @@ namespace libtorrent int size = m_torrent_file->piece_size(r.piece); if (rp->fail) { - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), r.piece, rp->error)); + m_ses.alerts().emplace_alert( + get_handle(), r.piece, rp->error); } else { - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), r.piece, rp->piece_data, size)); + m_ses.alerts().emplace_alert( + get_handle(), r.piece, rp->piece_data, size); } delete rp; } @@ -1650,7 +1650,7 @@ namespace libtorrent // if all went well, set the torrent ssl context to this one m_ssl_ctx = ctx; // tell the client we need a cert for this torrent - alerts().post_alert(torrent_need_cert_alert(get_handle())); + alerts().emplace_alert(get_handle()); #else set_error(asio::error::operation_not_supported, error_file_ssl_ctx); pause(); @@ -1765,7 +1765,7 @@ namespace libtorrent if (ev && m_ses.alerts().should_post()) { error_code ec = error_code(ev, get_libtorrent_category()); - m_ses.alerts().post_alert(fastresume_rejected_alert(get_handle(), ec, "", 0)); + m_ses.alerts().emplace_alert(get_handle(), ec, "", (char const*)0); } if (ev) @@ -2314,8 +2314,8 @@ namespace libtorrent if ((j->error || j->ret != 0) && m_resume_data && m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(fastresume_rejected_alert(get_handle(), j->error.ec - , resolve_filename(j->error.file), j->error.operation_str())); + m_ses.alerts().emplace_alert(get_handle(), j->error.ec + , resolve_filename(j->error.file), j->error.operation_str()); } #if defined TORRENT_LOGGING @@ -2637,8 +2637,8 @@ namespace libtorrent m_checking_piece = 0; m_num_checked_pieces = 0; if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(file_error_alert(j->error.ec, - resolve_filename(j->error.file), j->error.operation_str(), get_handle())); + m_ses.alerts().emplace_alert(j->error.ec, + resolve_filename(j->error.file), j->error.operation_str(), get_handle()); #if defined TORRENT_LOGGING debug_log("on_piece_hashed, fatal disk error: (%d) %s", j->error.ec.value(), j->error.ec.message().c_str()); @@ -2699,7 +2699,7 @@ namespace libtorrent // we are in graceful pause mode, and we just completed the last outstanding job. // now we can be considered paused if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); + alerts().emplace_alert(get_handle()); } // we paused the checking @@ -2910,8 +2910,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(dht_reply_alert( - get_handle(), peers.size())); + m_ses.alerts().emplace_alert( + get_handle(), peers.size()); } if (torrent_file().priv() || (torrent_file().is_i2p() @@ -2936,7 +2936,7 @@ namespace libtorrent if (m_trackers.empty()) { #if defined TORRENT_LOGGING - debug_log("*** announce_with_tracker: no trackers"); + debug_log("*** announce: no trackers"); #endif return; } @@ -2948,7 +2948,7 @@ namespace libtorrent if (e != tracker_request::stopped && !m_announce_to_trackers) { #if defined TORRENT_LOGGING - debug_log("*** announce_with_tracker: event != stopped && !m_announce_to_trackers"); + debug_log("*** announce: event != stopped && !m_announce_to_trackers"); #endif return; } @@ -2957,7 +2957,7 @@ namespace libtorrent if (e != tracker_request::stopped && !m_allow_peers) { #if defined TORRENT_LOGGING - debug_log("*** announce_with_tracker: event != stopped && !m_allow_peers"); + debug_log("*** announce: event != stopped && !m_allow_peers"); #endif return; } @@ -3009,11 +3009,11 @@ namespace libtorrent { announce_entry& ae = m_trackers[i]; #if defined TORRENT_LOGGING - debug_log("*** announce with tracker: considering \"%s\" " - "[ announce_to_all_tiers: %d announce_to_all_trackers: %d" - " i->tier: %d tier: %d " - " is_working: %d fails: %d fail_limit: %d updating: %d" - " can_announce: %d sent_announce: %d ]" + debug_log("*** tracker: \"%s\" " + "[ tiers: %d trackers: %d" + " i->tier: %d tier: %d" + " working: %d fails: %d limit: %d upd: %d" + " can: %d sent: %d ]" , ae.url.c_str(), settings().get_bool(settings_pack::announce_to_all_tiers) , settings().get_bool(settings_pack::announce_to_all_trackers) , ae.tier, tier, ae.is_working(), ae.fails, ae.fail_limit @@ -3064,9 +3064,8 @@ namespace libtorrent ae.next_announce = now + minutes(10); if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - anonymous_mode_alert(get_handle() - , anonymous_mode_alert::tracker_not_anonymous, req.url)); + m_ses.alerts().emplace_alert(get_handle() + , anonymous_mode_alert::tracker_not_anonymous, req.url); } continue; } @@ -3082,9 +3081,8 @@ namespace libtorrent ae.next_announce = now + minutes(10); if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - anonymous_mode_alert(get_handle() - , anonymous_mode_alert::tracker_not_anonymous, req.url)); + m_ses.alerts().emplace_alert(get_handle() + , anonymous_mode_alert::tracker_not_anonymous, req.url); } continue; } @@ -3117,8 +3115,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - tracker_announce_alert(get_handle(), req.url, req.event)); + m_ses.alerts().emplace_alert( + get_handle(), req.url, req.event); } sent_announce = true; @@ -3158,7 +3156,7 @@ namespace libtorrent INVARIANT_CHECK; if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(tracker_warning_alert(get_handle(), req.url, msg)); + m_ses.alerts().emplace_alert(get_handle(), req.url, msg); } void torrent::tracker_scrape_response(tracker_request const& req @@ -3181,8 +3179,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(scrape_reply_alert( - get_handle(), incomplete, complete, req.url)); + m_ses.alerts().emplace_alert( + get_handle(), incomplete, complete, req.url); } } @@ -3260,8 +3258,8 @@ namespace libtorrent { ae->trackerid = resp.trackerid; if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(trackerid_alert(get_handle() - , r.url, resp.trackerid)); + m_ses.alerts().emplace_alert(get_handle() + , r.url, resp.trackerid); } update_scrape_state(); @@ -3374,12 +3372,12 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(tracker_reply_alert( + m_ses.alerts().emplace_alert( get_handle(), resp.peers.size() + resp.peers4.size() #if TORRENT_USE_IPV6 + resp.peers6.size() #endif - , r.url)); + , r.url); } m_got_tracker_response = true; @@ -3588,8 +3586,8 @@ namespace libtorrent debug_log("blocked ip from tracker: %s", host.address().to_string(ec).c_str()); #endif if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(peer_blocked_alert(get_handle() - , host.address(), peer_blocked_alert::ip_filter)); + m_ses.alerts().emplace_alert(get_handle() + , host.address(), peer_blocked_alert::ip_filter); return; } @@ -4116,7 +4114,7 @@ namespace libtorrent state_updated(); if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(piece_finished_alert(get_handle(), index)); + m_ses.alerts().emplace_alert(get_handle(), index); // update m_file_progress (if we have one) if (!m_file_progress.empty()) @@ -4144,8 +4142,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { // this file just completed, post alert - m_ses.alerts().post_alert(file_completed_alert(get_handle() - , file_index)); + m_ses.alerts().emplace_alert(get_handle() + , file_index); } } } @@ -4289,7 +4287,7 @@ namespace libtorrent inc_stats_counter(counters::num_piece_failed); if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(hash_failed_alert(get_handle(), index)); + m_ses.alerts().emplace_alert(get_handle(), index); std::vector::iterator i = std::lower_bound(m_predictive_pieces.begin() , m_predictive_pieces.end(), index); @@ -4392,8 +4390,8 @@ namespace libtorrent { peer_id pid(0); if (p->connection) pid = p->connection->pid(); - m_ses.alerts().post_alert(peer_ban_alert( - get_handle(), p->ip(), pid)); + m_ses.alerts().emplace_alert( + get_handle(), p->ip(), pid); } // mark the peer as banned @@ -4786,7 +4784,7 @@ namespace libtorrent { TORRENT_ASSERT(m_abort); if (alerts().should_post()) - alerts().post_alert(cache_flushed_alert(get_handle())); + alerts().emplace_alert(get_handle()); } m_storage.reset(); @@ -4877,12 +4875,12 @@ namespace libtorrent if (j->ret != 0) { if (alerts().should_post()) - alerts().post_alert(torrent_delete_failed_alert(get_handle() - , j->error.ec, m_torrent_file->info_hash())); + alerts().emplace_alert(get_handle() + , j->error.ec, m_torrent_file->info_hash()); } else { - alerts().post_alert(torrent_deleted_alert(get_handle(), m_torrent_file->info_hash())); + alerts().emplace_alert(get_handle(), m_torrent_file->info_hash()); } } @@ -4895,15 +4893,15 @@ namespace libtorrent if (!j->buffer) { - alerts().post_alert(save_resume_data_failed_alert(get_handle(), j->error.ec)); + alerts().emplace_alert(get_handle(), j->error.ec); return; } m_need_save_resume_data = false; m_last_saved_resume = m_ses.session_time(); write_resume_data(*((entry*)j->buffer)); - alerts().post_alert(save_resume_data_alert(boost::shared_ptr((entry*)j->buffer) - , get_handle())); + alerts().emplace_alert( + boost::shared_ptr((entry*)j->buffer), get_handle()); const_cast(j)->buffer = 0; state_updated(); } @@ -4916,14 +4914,14 @@ namespace libtorrent if (j->ret == 0) { if (alerts().should_post()) - alerts().post_alert(file_renamed_alert(get_handle(), j->buffer, j->piece)); + alerts().emplace_alert(get_handle(), j->buffer, j->piece); m_torrent_file->rename_file(j->piece, j->buffer); } else { if (alerts().should_post()) - alerts().post_alert(file_rename_failed_alert(get_handle() - , j->piece, j->error.ec)); + alerts().emplace_alert(get_handle() + , j->piece, j->error.ec); } } @@ -4932,7 +4930,7 @@ namespace libtorrent TORRENT_ASSERT(is_single_thread()); if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); + alerts().emplace_alert(get_handle()); } // TODO: 2 the tracker login feature should probably be deprecated @@ -4998,8 +4996,8 @@ namespace libtorrent // failed if (flags & torrent_handle::alert_when_available) { - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category()))); + m_ses.alerts().emplace_alert( + get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category())); } return; } @@ -5133,8 +5131,8 @@ namespace libtorrent else if (i->flags & torrent_handle::alert_when_available) { // post an empty read_piece_alert to indicate it failed - alerts().post_alert(read_piece_alert( - get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category()))); + alerts().emplace_alert( + get_handle(), piece, error_code(boost::system::errc::operation_canceled, system_category())); } if (has_picker()) m_picker->set_piece_priority(piece, 1); m_time_critical_pieces.erase(i); @@ -5150,8 +5148,8 @@ namespace libtorrent if (i->flags & torrent_handle::alert_when_available) { // post an empty read_piece_alert to indicate it failed - m_ses.alerts().post_alert(read_piece_alert( - get_handle(), i->piece, error_code(boost::system::errc::operation_canceled, system_category()))); + m_ses.alerts().emplace_alert( + get_handle(), i->piece, error_code(boost::system::errc::operation_canceled, system_category())); } if (has_picker()) m_picker->set_piece_priority(i->piece, 1); i = m_time_critical_pieces.erase(i); @@ -5169,8 +5167,8 @@ namespace libtorrent if (i->flags & torrent_handle::alert_when_available) { // post an empty read_piece_alert to indicate it failed - alerts().post_alert(read_piece_alert( - get_handle(), i->piece, error_code(boost::system::errc::operation_canceled, system_category()))); + alerts().emplace_alert( + get_handle(), i->piece, error_code(boost::system::errc::operation_canceled, system_category())); } i = m_time_critical_pieces.erase(i); continue; @@ -5799,8 +5797,8 @@ namespace libtorrent if (!m_ssl_ctx) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle() - , error_code(errors::not_an_ssl_torrent), "")); + alerts().emplace_alert(get_handle() + , error_code(errors::not_an_ssl_torrent), ""); return; } @@ -5810,25 +5808,25 @@ namespace libtorrent if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, "")); + alerts().emplace_alert(get_handle(), ec, ""); } m_ssl_ctx->use_certificate_file(certificate, context::pem, ec); if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, certificate)); + alerts().emplace_alert(get_handle(), ec, certificate); } m_ssl_ctx->use_private_key_file(private_key, context::pem, ec); if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, private_key)); + alerts().emplace_alert(get_handle(), ec, private_key); } m_ssl_ctx->use_tmp_dh_file(dh_params, ec); if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, dh_params)); + alerts().emplace_alert(get_handle(), ec, dh_params); } } @@ -5840,8 +5838,8 @@ namespace libtorrent #if BOOST_VERSION < 105400 if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle() - , error_code(boost::system::errc::not_supported, system_category()), "[certificate]")); + alerts().emplace_alert(get_handle() + , error_code(boost::system::errc::not_supported, system_category()), "[certificate]"); #else boost::asio::const_buffer certificate_buf(certificate.c_str(), certificate.size()); @@ -5851,7 +5849,7 @@ namespace libtorrent if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, "[certificate]")); + alerts().emplace_alert(get_handle(), ec, "[certificate]"); } boost::asio::const_buffer private_key_buf(private_key.c_str(), private_key.size()); @@ -5859,7 +5857,7 @@ namespace libtorrent if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, "[private key]")); + alerts().emplace_alert(get_handle(), ec, "[private key]"); } boost::asio::const_buffer dh_params_buf(dh_params.c_str(), dh_params.size()); @@ -5867,7 +5865,7 @@ namespace libtorrent if (ec) { if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, "[dh params]")); + alerts().emplace_alert(get_handle(), ec, "[dh params]"); } #endif // BOOST_VERSION } @@ -6004,8 +6002,8 @@ namespace libtorrent #endif if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, ec)); + m_ses.alerts().emplace_alert(get_handle() + , web->url, ec); } // never try it again remove_web_seed(web); @@ -6019,9 +6017,8 @@ namespace libtorrent #endif if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url - , error_code(libtorrent::errors::peer_banned, get_libtorrent_category()))); + m_ses.alerts().emplace_alert(get_handle(), web->url + , error_code(libtorrent::errors::peer_banned, get_libtorrent_category())); } // never try it again remove_web_seed(web); @@ -6036,8 +6033,7 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, errors::unsupported_url_protocol)); + m_ses.alerts().emplace_alert(get_handle(), web->url, errors::unsupported_url_protocol); } // never try it again remove_web_seed(web); @@ -6048,8 +6044,8 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, errors::invalid_hostname)); + m_ses.alerts().emplace_alert(get_handle(), web->url + , errors::invalid_hostname); } // never try it again remove_web_seed(web); @@ -6060,8 +6056,8 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, errors::invalid_port)); + m_ses.alerts().emplace_alert(get_handle(), web->url + , errors::invalid_port); } // never try it again remove_web_seed(web); @@ -6072,8 +6068,8 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, errors::port_blocked)); + m_ses.alerts().emplace_alert(get_handle() + , web->url, errors::port_blocked); } // never try it again remove_web_seed(web); @@ -6154,8 +6150,8 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, e)); + m_ses.alerts().emplace_alert(get_handle() + , web->url, e); } // the name lookup failed for the http host. Don't try @@ -6184,8 +6180,8 @@ namespace libtorrent { if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert( - url_seed_alert(get_handle(), web->url, ec)); + m_ses.alerts().emplace_alert(get_handle() + , web->url, ec); } remove_web_seed(web); return; @@ -6195,8 +6191,8 @@ namespace libtorrent && m_ses.get_ip_filter().access(a.address()) & ip_filter::blocked) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(peer_blocked_alert(get_handle() - , a.address(), peer_blocked_alert::ip_filter)); + m_ses.alerts().emplace_alert(get_handle() + , a.address(), peer_blocked_alert::ip_filter); return; } @@ -6235,7 +6231,7 @@ namespace libtorrent if (e || addrs.empty()) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(url_seed_alert(get_handle(), web->url, e)); + m_ses.alerts().emplace_alert(get_handle(), web->url, e); #if defined TORRENT_LOGGING debug_log("*** HOSTNAME LOOKUP FAILED: %s: (%d) %s" , web->url.c_str(), e.value(), e.message().c_str()); @@ -6275,8 +6271,8 @@ namespace libtorrent && m_ses.get_ip_filter().access(a.address()) & ip_filter::blocked) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(peer_blocked_alert(get_handle() - , a.address(), peer_blocked_alert::ip_filter)); + m_ses.alerts().emplace_alert(get_handle() + , a.address(), peer_blocked_alert::ip_filter); return; } @@ -6324,7 +6320,7 @@ namespace libtorrent if (ec) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(url_seed_alert(get_handle(), web->url, ec)); + m_ses.alerts().emplace_alert(get_handle(), web->url, ec); return; } @@ -6351,7 +6347,7 @@ namespace libtorrent if (ec) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(url_seed_alert(get_handle(), web->url, ec)); + m_ses.alerts().emplace_alert(get_handle(), web->url, ec); return; } @@ -7331,8 +7327,8 @@ namespace libtorrent // we have an i2p torrent, but we're not connected to an i2p // SAM proxy. if (alerts().should_post()) - alerts().post_alert(i2p_alert(error_code(errors::no_i2p_router - , get_libtorrent_category()))); + alerts().emplace_alert(error_code(errors::no_i2p_router + , get_libtorrent_category())); return false; } @@ -7484,8 +7480,8 @@ namespace libtorrent { if (alerts().should_post()) { - alerts().post_alert(metadata_failed_alert(get_handle() - , error_code(errors::mismatching_info_hash, get_libtorrent_category()))); + alerts().emplace_alert(get_handle() + , error_code(errors::mismatching_info_hash, get_libtorrent_category())); } return false; } @@ -7501,7 +7497,7 @@ namespace libtorrent // failed to parse it. Pause the torrent if (alerts().should_post()) { - alerts().post_alert(metadata_failed_alert(get_handle(), ec)); + alerts().emplace_alert(get_handle(), ec); } set_error(errors::invalid_swarm_metadata, error_file_none); pause(); @@ -7512,8 +7508,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(metadata_received_alert( - get_handle())); + m_ses.alerts().emplace_alert( + get_handle()); } // this makes the resume data "paused" and @@ -7644,8 +7640,8 @@ namespace libtorrent && m_ses.get_ip_filter().access(p->remote().address()) & ip_filter::blocked) { if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(peer_blocked_alert(get_handle() - , p->remote().address(), peer_blocked_alert::ip_filter)); + m_ses.alerts().emplace_alert(get_handle() + , p->remote().address(), peer_blocked_alert::ip_filter); p->disconnect(errors::banned_by_ip_filter, op_bittorrent); return false; } @@ -8209,8 +8205,8 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(torrent_checked_alert( - get_handle())); + m_ses.alerts().emplace_alert( + get_handle()); } // calling pause will also trigger the auto managed @@ -8324,9 +8320,9 @@ namespace libtorrent if (!m_storage.get()) { if (alerts().should_post()) - alerts().post_alert(file_rename_failed_alert(get_handle() + alerts().emplace_alert(get_handle() , index, error_code(errors::session_is_closing - , get_libtorrent_category()))); + , get_libtorrent_category())); return; } @@ -8344,8 +8340,8 @@ namespace libtorrent if (m_abort) { if (alerts().should_post()) - alerts().post_alert(storage_moved_failed_alert(get_handle(), boost::asio::error::operation_aborted - , "", "")); + alerts().emplace_alert(get_handle(), boost::asio::error::operation_aborted + , "", ""); return; } @@ -8374,7 +8370,7 @@ namespace libtorrent if (alerts().should_post()) { - alerts().post_alert(storage_moved_alert(get_handle(), m_save_path)); + alerts().emplace_alert(get_handle(), m_save_path); } } } @@ -8388,7 +8384,7 @@ namespace libtorrent if (j->ret == piece_manager::no_error || j->ret == piece_manager::need_full_check) { if (alerts().should_post()) - alerts().post_alert(storage_moved_alert(get_handle(), j->buffer)); + alerts().emplace_alert(get_handle(), j->buffer); m_save_path = j->buffer; m_need_save_resume_data = true; if (j->ret == piece_manager::need_full_check) @@ -8397,8 +8393,8 @@ namespace libtorrent else { if (alerts().should_post()) - alerts().post_alert(storage_moved_failed_alert(get_handle(), j->error.ec - , resolve_filename(j->error.file), j->error.operation_str())); + alerts().emplace_alert(get_handle(), j->error.ec + , resolve_filename(j->error.file), j->error.operation_str()); } } @@ -8839,7 +8835,8 @@ namespace libtorrent update_gauge(); if (alerts().should_post()) - alerts().post_alert(torrent_error_alert(get_handle(), ec, resolve_filename(error_file))); + alerts().emplace_alert(get_handle(), ec + , resolve_filename(error_file)); #if defined TORRENT_LOGGING if (ec) @@ -9007,22 +9004,22 @@ namespace libtorrent if (!valid_metadata()) { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , errors::no_metadata)); + alerts().emplace_alert(get_handle() + , errors::no_metadata); return; } if (!m_storage.get()) { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , errors::destructing_torrent)); + alerts().emplace_alert(get_handle() + , errors::destructing_torrent); return; } if ((flags & torrent_handle::only_if_modified) && !m_need_save_resume_data) { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , errors::resume_data_not_modified)); + alerts().emplace_alert(get_handle() + , errors::resume_data_not_modified); return; } @@ -9037,14 +9034,14 @@ namespace libtorrent { if (!need_loaded()) { - alerts().post_alert(save_resume_data_failed_alert(get_handle() - , m_error)); + alerts().emplace_alert(get_handle() + , m_error); return; } boost::shared_ptr rd(new entry); write_resume_data(*rd); - alerts().post_alert(save_resume_data_alert(rd, get_handle())); + alerts().emplace_alert(rd, get_handle()); return; } @@ -9059,14 +9056,15 @@ namespace libtorrent { if (!need_loaded()) { - alerts().post_alert(save_resume_data_failed_alert(get_handle(), m_error)); + alerts().emplace_alert(get_handle(), m_error); return false; } // storage may be NULL during shutdown if (!m_storage) { TORRENT_ASSERT(m_abort); - alerts().post_alert(save_resume_data_failed_alert(get_handle(), boost::asio::error::operation_aborted)); + alerts().emplace_alert(get_handle() + , boost::asio::error::operation_aborted); return false; } inc_refcount("save_resume"); @@ -9110,7 +9108,7 @@ namespace libtorrent if (m_ses.is_aborted()) return; if (alerts().should_post()) - alerts().post_alert(cache_flushed_alert(get_handle())); + alerts().emplace_alert(get_handle()); } bool torrent::is_paused() const @@ -9192,7 +9190,7 @@ namespace libtorrent if (m_checking_piece == m_num_checked_pieces) { if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); + alerts().emplace_alert(get_handle()); } disconnect_all(errors::torrent_paused, op_bittorrent); return; @@ -9211,7 +9209,7 @@ namespace libtorrent else { if (alerts().should_post()) - alerts().post_alert(torrent_paused_alert(get_handle())); + alerts().emplace_alert(get_handle()); } disconnect_all(errors::torrent_paused, op_bittorrent); @@ -9376,7 +9374,7 @@ namespace libtorrent #endif if (alerts().should_post()) - alerts().post_alert(torrent_resumed_alert(get_handle())); + alerts().emplace_alert(get_handle()); m_started = m_ses.session_time(); if (is_seed()) m_became_seed = m_started; @@ -9415,10 +9413,10 @@ namespace libtorrent { #if defined TORRENT_LOGGING char msg[1000]; - snprintf(msg, sizeof(msg), "*** update tracker timer: considering \"%s\" " - "[ announce_to_all_tiers: %d announce_to_all_trackers: %d" - " found_working: %d i->tier: %d tier: %d " - " is_working: %d fails: %d fail_limit: %d updating: %d ]" + snprintf(msg, sizeof(msg), "*** tracker: \"%s\" " + "[ tiers: %d trackers: %d" + " found: %d i->tier: %d tier: %d" + " working: %d fails: %d limit: %d upd: %d ]" , i->url.c_str(), settings().get_bool(settings_pack::announce_to_all_tiers) , settings().get_bool(settings_pack::announce_to_all_trackers), found_working , i->tier, tier, i->is_working(), i->fails, i->fail_limit @@ -9660,16 +9658,16 @@ namespace libtorrent && m_stat.download_ip_overhead() >= down_limit && alerts().should_post()) { - alerts().post_alert(performance_alert(get_handle() - , performance_alert::download_limit_too_low)); + alerts().emplace_alert(get_handle() + , performance_alert::download_limit_too_low); } if (up_limit > 0 && m_stat.upload_ip_overhead() >= up_limit && alerts().should_post()) { - alerts().post_alert(performance_alert(get_handle() - , performance_alert::upload_limit_too_low)); + alerts().emplace_alert(get_handle() + , performance_alert::upload_limit_too_low); } } @@ -9743,7 +9741,7 @@ namespace libtorrent } } if (m_ses.alerts().should_post()) - m_ses.alerts().post_alert(stats_alert(get_handle(), tick_interval_ms, m_stat)); + m_ses.alerts().emplace_alert(get_handle(), tick_interval_ms, m_stat); m_total_uploaded += m_stat.last_payload_uploaded(); m_total_downloaded += m_stat.last_payload_downloaded(); @@ -10772,8 +10770,8 @@ namespace libtorrent && m_ses.get_ip_filter().access(adr.address()) & ip_filter::blocked) { if (alerts().should_post()) - alerts().post_alert(peer_blocked_alert(get_handle() - , adr.address(), peer_blocked_alert::ip_filter)); + alerts().emplace_alert(get_handle() + , adr.address(), peer_blocked_alert::ip_filter); #ifndef TORRENT_DISABLE_EXTENSIONS notify_extension_add_peer(adr, source, torrent_plugin::filtered); @@ -10784,8 +10782,8 @@ namespace libtorrent if (m_ses.get_port_filter().access(adr.port()) & port_filter::blocked) { if (alerts().should_post()) - alerts().post_alert(peer_blocked_alert(get_handle() - , adr.address(), peer_blocked_alert::port_filter)); + alerts().emplace_alert(get_handle() + , adr.address(), peer_blocked_alert::port_filter); #ifndef TORRENT_DISABLE_EXTENSIONS notify_extension_add_peer(adr, source, torrent_plugin::filtered); #endif @@ -10798,8 +10796,8 @@ namespace libtorrent if (!settings().get_bool(settings_pack::allow_i2p_mixed) && is_i2p()) { if (alerts().should_post()) - alerts().post_alert(peer_blocked_alert(get_handle() - , adr.address(), peer_blocked_alert::i2p_mixed)); + alerts().emplace_alert(get_handle() + , adr.address(), peer_blocked_alert::i2p_mixed); return NULL; } #endif @@ -10807,8 +10805,8 @@ namespace libtorrent if (settings().get_bool(settings_pack::no_connect_privileged_ports) && adr.port() < 1024) { if (alerts().should_post()) - alerts().post_alert(peer_blocked_alert(get_handle() - , adr.address(), peer_blocked_alert::privileged_ports)); + alerts().emplace_alert(get_handle() + , adr.address(), peer_blocked_alert::privileged_ports); #ifndef TORRENT_DISABLE_EXTENSIONS notify_extension_add_peer(adr, source, torrent_plugin::filtered); #endif @@ -10927,8 +10925,8 @@ namespace libtorrent { for (std::vector
::iterator i = banned.begin() , end(banned.end()); i != end; ++i) - alerts().post_alert(peer_blocked_alert(get_handle(), *i - , peer_blocked_alert::ip_filter)); + alerts().emplace_alert(get_handle(), *i + , peer_blocked_alert::ip_filter); } peers_erased(st.erased); @@ -10947,8 +10945,8 @@ namespace libtorrent { for (std::vector
::iterator i = banned.begin() , end(banned.end()); i != end; ++i) - alerts().post_alert(peer_blocked_alert(get_handle(), *i - , peer_blocked_alert::port_filter)); + alerts().emplace_alert(get_handle(), *i + , peer_blocked_alert::port_filter); } peers_erased(st.erased); @@ -11226,15 +11224,15 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(state_changed_alert(get_handle() - , s, (torrent_status::state_t)m_state)); + m_ses.alerts().emplace_alert(get_handle() + , s, (torrent_status::state_t)m_state); } if (s == torrent_status::finished && alerts().should_post()) { - alerts().post_alert(torrent_finished_alert( - get_handle())); + alerts().emplace_alert( + get_handle()); } m_state = s; @@ -11601,8 +11599,8 @@ namespace libtorrent } if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(tracker_error_alert(get_handle() - , ae?ae->fails:0, response_code, r.url, ec, msg)); + m_ses.alerts().emplace_alert(get_handle() + , ae?ae->fails:0, response_code, r.url, ec, msg); } } else if (r.kind == tracker_request::scrape_request) @@ -11616,7 +11614,7 @@ namespace libtorrent if (m_ses.alerts().should_post()) { - m_ses.alerts().post_alert(scrape_failed_alert(get_handle(), r.url, ec)); + m_ses.alerts().emplace_alert(get_handle(), r.url, ec); } } // announce to the next working tracker @@ -11637,8 +11635,8 @@ namespace libtorrent vsnprintf(buf, sizeof(buf), fmt, v); va_end(v); - alerts().post_alert(torrent_log_alert( - const_cast(this)->get_handle(), buf)); + alerts().emplace_alert( + const_cast(this)->get_handle(), buf); } #endif diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 1e879c141..825610223 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -822,8 +822,8 @@ namespace libtorrent { p = parent_path(p); // we don't want trailing slashes here - TORRENT_ASSERT(p.back() == *TORRENT_SEPARATOR); - p.pop_back(); + TORRENT_ASSERT(p[p.size() - 1] == *TORRENT_SEPARATOR); + p.resize(p.size() - 1); files.insert(p); } } diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 1dd9269e4..759ad1fbd 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -634,8 +634,8 @@ void web_peer_connection::on_receive(error_code const& error + (" " + m_parser.message()); if (t->alerts().should_post()) { - t->alerts().post_alert(url_seed_alert(t->get_handle(), m_url - , error_msg)); + t->alerts().emplace_alert(t->get_handle(), m_url + , error_msg); } received_bytes(0, bytes_transferred); disconnect(error_code(m_parser.status_code(), get_http_category()), op_bittorrent, 1); diff --git a/test/Jamfile b/test/Jamfile index 525225f13..08c9c4d2a 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -95,8 +95,10 @@ feature launcher : none valgrind : composite ; feature.compose valgrind : "valgrind --tool=memcheck -v --num-callers=20 --read-var-info=yes --track-origins=yes --error-exitcode=222 --suppressions=valgrind_suppressions.txt" on ; test-suite libtorrent : + [ run test_alert_manager.cpp ] [ run test_resolve_links.cpp ] [ run test_crc32.cpp ] + [ run test_heterogeneous_queue.cpp ] [ run test_resume.cpp ] [ run test_sliding_average.cpp ] [ run test_socket_io.cpp ] diff --git a/test/Makefile.am b/test/Makefile.am index 6bdba2fec..2258a05a1 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,7 @@ AUTOMAKE_OPTIONS = subdir-objects test_programs = \ + test_alert_manager \ test_bitfield \ test_crc32 \ test_torrent_info \ @@ -20,6 +21,7 @@ test_programs = \ test_checking \ test_fast_extension \ test_hasher \ + test_heterogeneous_queue \ test_http_connection \ test_ip_filter \ test_dht \ diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index eca34598f..c30e0bb5f 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -127,13 +127,13 @@ std::map get_counters(libtorrent::session& s) s.post_session_stats(); std::map ret; - std::auto_ptr a = wait_for_alert(s, session_stats_alert::alert_type + alert const* a = wait_for_alert(s, session_stats_alert::alert_type , "get_counters()"); - TEST_CHECK(a.get()); - if (!a.get()) return ret; + TEST_CHECK(a); + if (!a) return ret; - session_stats_alert* sa = alert_cast(a.get()); + session_stats_alert const* sa = alert_cast(a); if (!sa) return ret; static std::vector metrics = session_stats_metrics(); @@ -142,32 +142,29 @@ std::map get_counters(libtorrent::session& s) return ret; } -std::auto_ptr wait_for_alert(lt::session& ses, int type, char const* name) +alert const* wait_for_alert(lt::session& ses, int type, char const* name) { - std::auto_ptr ret; time_point end = libtorrent::clock_type::now() + seconds(10); - while (!ret.get()) + while (true) { time_point now = clock_type::now(); - if (now > end) return std::auto_ptr(); + if (now > end) return NULL; ses.wait_for_alert(end - now); - std::deque alerts; + std::vector alerts; ses.pop_alerts(&alerts); - for (std::deque::iterator i = alerts.begin() + for (std::vector::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { fprintf(stderr, "%s: %s: [%s] %s\n", aux::time_now_string(), name , (*i)->what(), (*i)->message().c_str()); - if (!ret.get() && (*i)->type() == type) + if ((*i)->type() == type) { - ret = std::auto_ptr(*i); + return *i; } - else - delete *i; } } - return ret; + return NULL; } int load_file(std::string const& filename, std::vector& v, libtorrent::error_code& ec, int limit) @@ -254,19 +251,19 @@ void save_file(char const* filename, char const* data, int size) bool print_alerts(lt::session& ses, char const* name , bool allow_disconnects, bool allow_no_torrents, bool allow_failed_fastresume - , bool (*predicate)(libtorrent::alert*), bool no_output) + , bool (*predicate)(libtorrent::alert const*), bool no_output) { bool ret = false; std::vector handles = ses.get_torrents(); TEST_CHECK(!handles.empty() || allow_no_torrents); torrent_handle h; if (!handles.empty()) h = handles[0]; - std::deque alerts; + std::vector alerts; ses.pop_alerts(&alerts); - for (std::deque::iterator i = alerts.begin(); i != alerts.end(); ++i) + for (std::vector::iterator i = alerts.begin(); i != alerts.end(); ++i) { if (predicate && predicate(*i)) ret = true; - if (peer_disconnected_alert* p = alert_cast(*i)) + if (peer_disconnected_alert const* p = alert_cast(*i)) { fprintf(stderr, "%s: %s: [%s] (%s): %s\n", aux::time_now_string(), name, (*i)->what(), print_endpoint(p->ip).c_str(), p->message().c_str()); } @@ -280,7 +277,7 @@ bool print_alerts(lt::session& ses, char const* name TEST_CHECK(alert_cast(*i) == 0 || allow_failed_fastresume); /* - peer_error_alert* pea = alert_cast(*i); + peer_error_alert const* pea = alert_cast(*i); if (pea) { fprintf(stderr, "%s: peer error: %s\n", aux::time_now_string(), pea->error.message().c_str()); @@ -298,19 +295,18 @@ bool print_alerts(lt::session& ses, char const* name } */ - invalid_request_alert* ira = alert_cast(*i); + invalid_request_alert const* ira = alert_cast(*i); if (ira) { fprintf(stderr, "peer error: %s\n", ira->message().c_str()); TEST_CHECK(false); } - delete *i; } return ret; } bool listen_done = false; -bool listen_alert(libtorrent::alert* a) +bool listen_alert(libtorrent::alert const* a) { if (alert_cast(a) || alert_cast(a)) @@ -333,9 +329,9 @@ void wait_for_listen(lt::session& ses, char const* name) } bool downloading_done = false; -bool downloading_alert(libtorrent::alert* a) +bool downloading_alert(libtorrent::alert const* a) { - state_changed_alert* sc = alert_cast(a); + state_changed_alert const* sc = alert_cast(a); if (sc && sc->state == torrent_status::downloading) downloading_done = true; return true; diff --git a/test/setup_transfer.hpp b/test/setup_transfer.hpp index c18f189e7..0227af6ad 100644 --- a/test/setup_transfer.hpp +++ b/test/setup_transfer.hpp @@ -60,7 +60,7 @@ libtorrent::udp::endpoint EXPORT rand_udp_ep(); std::map EXPORT get_counters(libtorrent::session& s); -std::auto_ptr EXPORT wait_for_alert( +libtorrent::alert const* EXPORT wait_for_alert( libtorrent::session& ses, int type, char const* name = ""); void EXPORT print_ses_rate(float time @@ -72,7 +72,7 @@ bool EXPORT print_alerts(libtorrent::session& ses, char const* name , bool allow_disconnects = false , bool allow_no_torrents = false , bool allow_failed_fastresume = false - , bool (*)(libtorrent::alert*) = 0 + , bool (*)(libtorrent::alert const*) = 0 , bool no_output = false); void EXPORT wait_for_listen(libtorrent::session& ses, char const* name); diff --git a/test/swarm_suite.cpp b/test/swarm_suite.cpp index 57ed4578a..cec1a16c5 100644 --- a/test/swarm_suite.cpp +++ b/test/swarm_suite.cpp @@ -190,21 +190,9 @@ void test_swarm(int flags) ses2.remove_torrent(tor2, lt::session::delete_files); ses3.remove_torrent(tor3, lt::session::delete_files); - std::auto_ptr a = ses1.pop_alert(); - time_point end = clock_type::now() + seconds(20); - while (a.get() == 0 || alert_cast(a.get()) == 0) - { - if (ses1.wait_for_alert(end - clock_type::now()) == 0) - { - std::cerr << "wait_for_alert() expired" << std::endl; - break; - } - a = ses1.pop_alert(); - assert(a.get()); - std::cerr << a->message() << std::endl; - } + alert const* a = wait_for_alert(ses1, torrent_deleted_alert::alert_type, "swarm_suite"); - TEST_CHECK(alert_cast(a.get()) != 0); + TEST_CHECK(alert_cast(a) != 0); // there shouldn't be any alerts generated from now on // make sure that the timer in wait_for_alert() works @@ -214,8 +202,13 @@ void test_swarm(int flags) alert const* ret; while ((ret = ses1.wait_for_alert(seconds(2)))) { - a = ses1.pop_alert(); - std::cerr << ret->message() << std::endl; + std::vector alerts; + ses1.pop_alerts(&alerts); + for (std::vector::iterator i = alerts.begin() + , end(alerts.end()); i != end; ++i) + { + std::cerr << ret->message() << std::endl; + } start = clock_type::now(); } diff --git a/test/test_alert_manager.cpp b/test/test_alert_manager.cpp new file mode 100644 index 000000000..9906e03af --- /dev/null +++ b/test/test_alert_manager.cpp @@ -0,0 +1,183 @@ +/* + +Copyright (c) 2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "test.hpp" +#include "libtorrent/alert_manager.hpp" +#include "libtorrent/torrent_handle.hpp" +#include "libtorrent/alert_types.hpp" + +#include + +using namespace libtorrent; + +void test_limit() +{ + alert_manager mgr(500, 0xffffffff); + + TEST_EQUAL(mgr.alert_queue_size_limit(), 500); + TEST_EQUAL(mgr.pending(), false); + + // try add 600 torrent_add_alert to make sure we honor the limit of 500 + // alerts. + for (int i = 0; i < 600; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), true); + + std::vector alerts; + int num_resume; + mgr.get_all(alerts, num_resume); + + // even though we posted 600, the limit was 500 + TEST_EQUAL(alerts.size(), 500); + + TEST_EQUAL(mgr.pending(), false); +} + +void test_priority_limit() +{ + alert_manager mgr(100, 0xffffffff); + + TEST_EQUAL(mgr.alert_queue_size_limit(), 100); + + // this should only add 100 because of the limit + for (int i = 0; i < 200; ++i) + mgr.emplace_alert(torrent_handle()); + + // the limit is twice as high for priority alerts + for (int i = 0; i < 200; ++i) + mgr.emplace_alert(torrent_handle(), i, error_code()); + + std::vector alerts; + int num_resume; + mgr.get_all(alerts, num_resume); + + // even though we posted 400, the limit was 100 for half of them and + // 200 for the other half, meaning we should have 200 alerts now + TEST_EQUAL(alerts.size(), 200); +} + +void test_dispatch_fun(int& cnt, std::auto_ptr a) +{ + ++cnt; +} + +void test_dispatch_function() +{ +#ifndef TORRENT_NO_DEPRECATE + int cnt = 0; + alert_manager mgr(100, 0xffffffff); + + TEST_EQUAL(mgr.alert_queue_size_limit(), 100); + TEST_EQUAL(mgr.pending(), false); + + for (int i = 0; i < 20; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), true); + + mgr.set_dispatch_function(boost::bind(&test_dispatch_fun, boost::ref(cnt), _1)); + + TEST_EQUAL(mgr.pending(), false); + + TEST_EQUAL(cnt, 20); + + for (int i = 0; i < 200; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), false); + TEST_EQUAL(cnt, 220); +#endif +} + +void test_notify_fun(int& cnt) +{ + ++cnt; +} + +void test_notify_function() +{ + int cnt = 0; + alert_manager mgr(100, 0xffffffff); + + TEST_EQUAL(mgr.alert_queue_size_limit(), 100); + TEST_EQUAL(mgr.pending(), false); + + for (int i = 0; i < 20; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), true); + + // if there are queued alerts when we set the notify function, + // that counts as an edge and it's called + mgr.set_notify_function(boost::bind(&test_notify_fun, boost::ref(cnt))); + + TEST_EQUAL(mgr.pending(), true); + TEST_EQUAL(cnt, 1); + + // subsequent posted alerts will not cause an edge (because there are + // already alerts queued) + for (int i = 0; i < 20; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), true); + TEST_EQUAL(cnt, 1); + + // however, if we pop all the alerts and post new ones, there will be + // and edge triggering the notify call + std::vector alerts; + int num_resume; + mgr.get_all(alerts, num_resume); + + TEST_EQUAL(mgr.pending(), false); + + for (int i = 0; i < 20; ++i) + mgr.emplace_alert(torrent_handle()); + + TEST_EQUAL(mgr.pending(), true); + TEST_EQUAL(cnt, 2); +} + +int test_main() +{ + test_limit(); + test_priority_limit(); + test_dispatch_function(); + test_notify_function(); + + // TODO: test wait_for_alert + // TODO: test num_queued_resume + // TODO: test alert_mask + + return 0; +} + diff --git a/test/test_block_cache.cpp b/test/test_block_cache.cpp index ee4a47eb0..937d8b35b 100644 --- a/test/test_block_cache.cpp +++ b/test/test_block_cache.cpp @@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/alert_types.hpp" #include "libtorrent/disk_io_thread.hpp" #include "libtorrent/storage.hpp" -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/session.hpp" #include @@ -46,16 +45,6 @@ POSSIBILITY OF SUCH DAMAGE. using namespace libtorrent; -struct print_alert : alert_dispatcher -{ - virtual bool post_alert(alert* a) - { - fprintf(stderr, "ALERT: %s\n", a->message().c_str()); - delete a; - return true; - } -}; - struct test_storage_impl : storage_interface { virtual void initialize(storage_error& ec) {} @@ -97,8 +86,7 @@ void nop() {} #define TEST_SETUP \ io_service ios; \ - print_alert ad; \ - block_cache bc(0x4000, ios, boost::bind(&nop), &ad); \ + block_cache bc(0x4000, ios, boost::bind(&nop)); \ aux::session_settings sett; \ file_storage fs; \ fs.add_file("a/test0", 0x4000); \ @@ -113,7 +101,8 @@ void nop() {} fs.set_num_pieces(5); \ test_storage_impl* st = new test_storage_impl; \ boost::shared_ptr pm(boost::make_shared(st, boost::shared_ptr(new int), &fs)); \ - bc.set_settings(sett); \ + error_code ec; \ + bc.set_settings(sett, ec); \ st->m_settings = &sett; \ disk_io_job rj; \ disk_io_job wj; \ diff --git a/test/test_dht.cpp b/test/test_dht.cpp index 99efb4e7b..7c9cf1617 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bencode.hpp" #include "libtorrent/socket_io.hpp" // for hash_address #include "libtorrent/broadcast_socket.hpp" // for supports_ipv6 -#include "libtorrent/alert_dispatcher.hpp" #include "libtorrent/performance_counters.hpp" // for counters #include "libtorrent/random.hpp" #include "libtorrent/ed25519.hpp" @@ -396,17 +395,6 @@ void announce_immutable_items(node_impl& node, udp::endpoint const* eps // TEST_CHECK(items_num.find(3) != items_num.end()); } -struct print_alert : alert_dispatcher -{ - virtual bool post_alert(alert* a) - { - fprintf(stderr, "ALERT: %s\n", a->message().c_str()); - delete a; - return true; - } -}; - - int sum_distance_exp(int s, node_entry const& e, node_id const& ref) { return s + distance_exp(e.id, ref); @@ -445,9 +433,8 @@ int test_main() sett.enforce_node_id = false; address ext = address::from_string("236.0.0.1"); mock_socket s; - print_alert ad; counters cnt; - dht::node_impl node(&ad, &s, sett, node_id(0), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id(0), ext, 0, cnt); // DHT should be running on port 48199 now bdecode_node response; @@ -1464,7 +1451,7 @@ int test_main() g_sent_packets.clear(); do { - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); udp::endpoint initial_node(address_v4::from_string("4.4.4.4"), 1234); std::vector nodesv; @@ -1536,7 +1523,7 @@ int test_main() do { dht::node_id target = to_hash("1234876923549721020394873245098347598635"); - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); udp::endpoint initial_node(address_v4::from_string("4.4.4.4"), 1234); node.m_table.add_node(initial_node); @@ -1629,7 +1616,7 @@ int test_main() g_sent_packets.clear(); do { - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); udp::endpoint initial_node(address_v4::from_string("4.4.4.4"), 1234); node.m_table.add_node(initial_node); @@ -1675,7 +1662,7 @@ int test_main() g_sent_packets.clear(); do { - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); udp::endpoint initial_node(address_v4::from_string("4.4.4.4"), 1234); node.m_table.add_node(initial_node); @@ -1751,7 +1738,7 @@ int test_main() g_sent_packets.clear(); do { - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); enum { num_test_nodes = 2 }; node_entry nodes[num_test_nodes] = { node_entry(generate_next(), udp::endpoint(address_v4::from_string("4.4.4.4"), 1234)) @@ -1833,7 +1820,7 @@ int test_main() g_sent_packets.clear(); do { - dht::node_impl node(&ad, &s, sett, node_id::min(), ext, 0, cnt); + dht::node_impl node(&s, sett, node_id::min(), ext, 0, cnt); enum { num_test_nodes = 2 }; node_entry nodes[num_test_nodes] = { node_entry(generate_next(), udp::endpoint(address_v4::from_string("4.4.4.4"), 1234)) diff --git a/test/test_heterogeneous_queue.cpp b/test/test_heterogeneous_queue.cpp new file mode 100644 index 000000000..a7ea895fa --- /dev/null +++ b/test/test_heterogeneous_queue.cpp @@ -0,0 +1,290 @@ +/* + +Copyright (c) 2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "test.hpp" +#include "libtorrent/heterogeneous_queue.hpp" + +struct A +{ + int a; + explicit A(int a_) : a(a_) {} + virtual int type() = 0; + virtual ~A() {} +}; + +struct B : A +{ + int b; + explicit B(int a_, int b_) : A(a_), b(b_) {} + virtual int type() { return 1; } +}; + +struct C : A +{ + char c[100]; + explicit C(int a_, int c_) : A(a_) + { + memset(c, c_, sizeof(c)); + } + virtual int type() { return 2; } +}; + +struct D +{ + static int instances; + D() { ++instances; } + D(D const& d) { ++instances; } + + ~D() { --instances; } +}; + +struct E +{ + E(char const* msg) : string_member(msg) {} + std::string string_member; +}; + +int D::instances = 0; + +struct F +{ + F(int f_) + : self(this) + , f(f_) + , constructed(true) + , destructed(false) + , gutted(false) + {} + + F(F const& f_) + : self(this), f(f_.f) + , constructed(f_.constructed) + , destructed(f_.destructed) + , gutted(false) + { + TEST_EQUAL(f_.constructed, true); + TEST_EQUAL(f_.destructed, false); + TEST_EQUAL(f_.gutted, false); + } + +#if __cplusplus >= 201103L + F(F&& f_) + : self(this) + , f(f_.f) + , constructed(f_.constructed) + , destructed(f_.destructed) + { + TEST_EQUAL(f_.constructed, true); + TEST_EQUAL(f_.destructed, false); + TEST_EQUAL(f_.gutted, false); + f_.gutted = true; + } +#endif + + ~F() + { + TEST_EQUAL(constructed, true); + TEST_EQUAL(destructed, false); + TEST_EQUAL(self, this); + destructed = true; + constructed = false; + } + + void check_invariant() + { + TEST_EQUAL(constructed, true); + TEST_EQUAL(destructed, false); + TEST_EQUAL(gutted, false); + TEST_EQUAL(self, this); + } + + F* self; + int f; + bool constructed; + bool destructed; + bool gutted; +private: + // non-copyable + F& operator=(F const& f); +}; + +int test_main() +{ + using namespace libtorrent; + + // test push_back of heterogeneous types + // and retrieval of their pointers + { + heterogeneous_queue q; + q.push_back(B(0, 1)); + TEST_EQUAL(q.size(), 1); + q.push_back(B(2, 3)); + TEST_EQUAL(q.size(), 2); + q.push_back(B(4, 5)); + TEST_EQUAL(q.size(), 3); + q.push_back(C(6, 7)); + TEST_EQUAL(q.size(), 4); + q.push_back(C(8, 9)); + TEST_EQUAL(q.size(), 5); + q.push_back(C(10, 11)); + TEST_EQUAL(q.size(), 6); + + std::vector ptrs; + q.get_pointers(ptrs); + + TEST_EQUAL(ptrs.size(), q.size()); + TEST_EQUAL(ptrs[0]->type(), 1); + TEST_EQUAL(ptrs[1]->type(), 1); + TEST_EQUAL(ptrs[2]->type(), 1); + TEST_EQUAL(ptrs[3]->type(), 2); + TEST_EQUAL(ptrs[4]->type(), 2); + TEST_EQUAL(ptrs[5]->type(), 2); + + TEST_EQUAL(static_cast(ptrs[0])->a, 0); + TEST_EQUAL(static_cast(ptrs[0])->b, 1); + + TEST_EQUAL(static_cast(ptrs[1])->a, 2); + TEST_EQUAL(static_cast(ptrs[1])->b, 3); + + TEST_EQUAL(static_cast(ptrs[2])->a, 4); + TEST_EQUAL(static_cast(ptrs[2])->b, 5); + + TEST_EQUAL(static_cast(ptrs[3])->a, 6); + TEST_EQUAL(static_cast(ptrs[3])->c[0], 7); + + TEST_EQUAL(static_cast(ptrs[4])->a, 8); + TEST_EQUAL(static_cast(ptrs[4])->c[0], 9); + + TEST_EQUAL(static_cast(ptrs[5])->a, 10); + TEST_EQUAL(static_cast(ptrs[5])->c[0], 11); + } + + // test swap + { + heterogeneous_queue q1; + heterogeneous_queue q2; + + q1.push_back(B(0, 1)); + q1.push_back(B(2, 3)); + q1.push_back(B(4, 5)); + TEST_EQUAL(q1.size(), 3); + + q2.push_back(C(6, 7)); + q2.push_back(C(8, 9)); + TEST_EQUAL(q2.size(), 2); + + std::vector ptrs; + q1.get_pointers(ptrs); + TEST_EQUAL(ptrs.size(), q1.size()); + + TEST_EQUAL(ptrs[0]->type(), 1); + TEST_EQUAL(ptrs[1]->type(), 1); + TEST_EQUAL(ptrs[2]->type(), 1); + + q2.get_pointers(ptrs); + TEST_EQUAL(ptrs.size(), q2.size()); + + TEST_EQUAL(ptrs[0]->type(), 2); + TEST_EQUAL(ptrs[1]->type(), 2); + + q1.swap(q2); + + q1.get_pointers(ptrs); + TEST_EQUAL(q1.size(), 2); + TEST_EQUAL(ptrs.size(), q1.size()); + + TEST_EQUAL(ptrs[0]->type(), 2); + TEST_EQUAL(ptrs[1]->type(), 2); + + q2.get_pointers(ptrs); + TEST_EQUAL(q2.size(), 3); + TEST_EQUAL(ptrs.size(), q2.size()); + + TEST_EQUAL(ptrs[0]->type(), 1); + TEST_EQUAL(ptrs[1]->type(), 1); + TEST_EQUAL(ptrs[2]->type(), 1); + } + + // test destruction + { + heterogeneous_queue q; + TEST_EQUAL(D::instances, 0); + + q.push_back(D()); + TEST_EQUAL(D::instances, 1); + q.push_back(D()); + TEST_EQUAL(D::instances, 2); + q.push_back(D()); + TEST_EQUAL(D::instances, 3); + q.push_back(D()); + TEST_EQUAL(D::instances, 4); + + q.clear(); + + TEST_EQUAL(D::instances, 0); + } + + // test copy/move + { + heterogeneous_queue q; + + // make sure the queue has to grow at some point, to exercise its + // copy/move of elements + for (int i = 0; i < 1000; ++i) + q.push_back(F(i)); + + std::vector ptrs; + q.get_pointers(ptrs); + + TEST_EQUAL(ptrs.size(), 1000); + + for (int i = 0; i < ptrs.size(); ++i) + { + ptrs[i]->check_invariant(); + TEST_EQUAL(ptrs[i]->f, i); + } + + // destroy all objects, asserting that their invariant still holds + q.clear(); + } + + { + heterogeneous_queue q; + for (int i = 0; i < 10000; ++i) + { + q.push_back(E("testing to allocate non-trivial objects")); + } + } + + return 0; +} + diff --git a/test/test_priority.cpp b/test/test_priority.cpp index cbe74265e..01c7bdfc6 100644 --- a/test/test_priority.cpp +++ b/test/test_priority.cpp @@ -57,7 +57,7 @@ int peer_disconnects = 0; int tracker_responses = 0; -bool on_alert(alert* a) +bool on_alert(alert const* a) { if (alert_cast(a)) ++tracker_responses; @@ -259,28 +259,34 @@ void test_transfer(settings_pack const& sett) std::vector resume_data; - alert const* a = ses2.wait_for_alert(seconds(10)); time_point start = clock_type::now(); - while (a) + while (true) { - std::auto_ptr holder = ses2.pop_alert(); - std::cerr << "ses2: " << a->message() << std::endl; - if (alert_cast(a)) + std::vector alerts; + ses2.pop_alerts(&alerts); + if (alerts.empty()) break; + for (std::vector::iterator i = alerts.begin() + , end(alerts.end()); i != end; ++i) { - bencode(std::back_inserter(resume_data) + alert* a = *i; + std::cerr << "ses2: " << a->message() << std::endl; + if (alert_cast(a)) + { + bencode(std::back_inserter(resume_data) , *alert_cast(a)->resume_data); - fprintf(stderr, "saved resume data\n"); - break; - } - else if (alert_cast(a)) - { - fprintf(stderr, "save resume failed\n"); - break; - } - if (total_seconds(clock_type::now() - start) > 10) - break; + fprintf(stderr, "saved resume data\n"); + break; + } + else if (alert_cast(a)) + { + fprintf(stderr, "save resume failed\n"); + break; + } + if (total_seconds(clock_type::now() - start) > 10) + break; - a = ses2.wait_for_alert(seconds(10)); + ses2.wait_for_alert(seconds(10)); + } } TEST_CHECK(resume_data.size()); diff --git a/test/test_privacy.cpp b/test/test_privacy.cpp index 1df97feb7..8ffedf64b 100644 --- a/test/test_privacy.cpp +++ b/test/test_privacy.cpp @@ -56,9 +56,9 @@ char const* proxy_name[] = { std::vector rejected_trackers; -bool alert_predicate(libtorrent::alert* a) +bool alert_predicate(libtorrent::alert const* a) { - anonymous_mode_alert* am = alert_cast(a); + anonymous_mode_alert const* am = alert_cast(a); if (am == NULL) return false; if (am->kind == anonymous_mode_alert::tracker_not_anonymous) diff --git a/test/test_read_piece.cpp b/test/test_read_piece.cpp index e1eea0779..355f26701 100644 --- a/test/test_read_piece.cpp +++ b/test/test_read_piece.cpp @@ -101,8 +101,8 @@ void test_read_piece(int flags) TEST_CHECK(!ec); TEST_CHECK(tor1.is_valid()); - std::auto_ptr a = wait_for_alert(ses, torrent_finished_alert::alert_type, "ses"); - TEST_CHECK(a.get()); + alert const* a = wait_for_alert(ses, torrent_finished_alert::alert_type, "ses"); + TEST_CHECK(a); TEST_CHECK(tor1.status().is_seeding); @@ -117,10 +117,10 @@ void test_read_piece(int flags) a = wait_for_alert(ses, read_piece_alert::alert_type, "ses"); - TEST_CHECK(a.get()); - if (a.get()) + TEST_CHECK(a); + if (a) { - read_piece_alert* rp = alert_cast(a.get()); + read_piece_alert const* rp = alert_cast(a); TEST_CHECK(rp); if (rp) { diff --git a/test/test_remap_files.cpp b/test/test_remap_files.cpp index d22c50e3f..2847a66d2 100644 --- a/test/test_remap_files.cpp +++ b/test/test_remap_files.cpp @@ -51,7 +51,7 @@ boost::shared_ptr clone_ptr(boost::shared_ptr const& ptr) int peer_disconnects = 0; -bool on_alert(alert* a) +bool on_alert(alert const* a) { if (alert_cast(a)) ++peer_disconnects; @@ -138,8 +138,8 @@ void test_remap_files_gather(storage_mode_t storage_mode = storage_mode_sparse) for (int i = 0; i < 50; ++i) { - print_alerts(ses1, "ses1", true, true, true, on_alert); - print_alerts(ses2, "ses2", true, true, true, on_alert); + print_alerts(ses1, "ses1", true, true, true, &on_alert); + print_alerts(ses2, "ses2", true, true, true, &on_alert); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); @@ -181,7 +181,7 @@ void test_remap_files_gather(storage_mode_t storage_mode = storage_mode_sparse) for (int i = 0; i < 50; ++i) { - print_alerts(ses2, "ses2", true, true, true, on_alert); + print_alerts(ses2, "ses2", true, true, true, &on_alert); torrent_status st2 = tor2.status(); @@ -273,8 +273,8 @@ void test_remap_files_scatter(storage_mode_t storage_mode = storage_mode_sparse) for (int i = 0; i < 50; ++i) { - print_alerts(ses1, "ses1", true, true, true, on_alert); - print_alerts(ses2, "ses2", true, true, true, on_alert); + print_alerts(ses1, "ses1", true, true, true, &on_alert); + print_alerts(ses2, "ses2", true, true, true, &on_alert); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); @@ -316,7 +316,7 @@ void test_remap_files_scatter(storage_mode_t storage_mode = storage_mode_sparse) for (int i = 0; i < 50; ++i) { - print_alerts(ses2, "ses2", true, true, true, on_alert); + print_alerts(ses2, "ses2", true, true, true, &on_alert); torrent_status st2 = tor2.status(); @@ -440,8 +440,8 @@ void test_remap_files_prio(storage_mode_t storage_mode = storage_mode_sparse) for (int i = 0; i < 50; ++i) { - print_alerts(ses1, "ses1", true, true, true, on_alert); - print_alerts(ses2, "ses2", true, true, true, on_alert); + print_alerts(ses1, "ses1", true, true, true, &on_alert); + print_alerts(ses2, "ses2", true, true, true, &on_alert); torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); diff --git a/test/test_session.cpp b/test/test_session.cpp index 5f4414458..af81e6820 100644 --- a/test/test_session.cpp +++ b/test/test_session.cpp @@ -55,20 +55,20 @@ int test_main() // we're allowing a larger queue than we have cache. - std::auto_ptr a; + alert const* a; for (;;) { a = wait_for_alert(ses, performance_alert::alert_type, "ses1"); - if (a.get() == NULL) break; - TEST_EQUAL(a.get()->type(), performance_alert::alert_type); + if (a == NULL) break; + TEST_EQUAL(a->type(), performance_alert::alert_type); - if (alert_cast(a.get())->warning_code + if (alert_cast(a)->warning_code == performance_alert::too_high_disk_queue_limit) break; } - TEST_CHECK(a.get()); + TEST_CHECK(a); sett.set_int(settings_pack::unchoke_slots_limit, 0); ses.apply_settings(sett); diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 5a116aae0..bc7330402 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -204,7 +204,7 @@ void run_storage_tests(boost::shared_ptr info { // avoid having two storages use the same files file_pool fp; libtorrent::asio::io_service ios; - disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop), NULL); + disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop)); storage_params p; p.path = test_path; p.files = &fs; @@ -296,7 +296,7 @@ void test_remove(std::string const& test_path, bool unbuffered) std::vector buf; file_pool fp; io_service ios; - disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop), NULL); + disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop)); aux::session_settings set; set.set_int(settings_pack::disk_io_write_mode @@ -369,7 +369,7 @@ void test_rename(std::string const& test_path) std::vector buf; file_pool fp; io_service ios; - disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop), NULL); + disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop)); aux::session_settings set; boost::shared_ptr s = setup_torrent(fs, fp, buf, test_path @@ -446,8 +446,8 @@ void test_check_files(std::string const& test_path file_pool fp; libtorrent::asio::io_service ios; counters cnt; - disk_io_thread io(ios, NULL, cnt, NULL); - disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop), NULL); + disk_io_thread io(ios, cnt, NULL); + disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop)); storage_params p; p.files = &fs; p.path = test_path; @@ -653,11 +653,12 @@ void test_fastresume(std::string const& test_path) return; h.save_resume_data(); - std::auto_ptr ra = wait_for_alert(ses, save_resume_data_alert::alert_type); - TEST_CHECK(ra.get()); - if (ra.get()) resume = *alert_cast(ra.get())->resume_data; + alert const* ra = wait_for_alert(ses, save_resume_data_alert::alert_type); + TEST_CHECK(ra); + if (ra) resume = *alert_cast(ra)->resume_data; ses.remove_torrent(h, lt::session::delete_files); - std::auto_ptr da = wait_for_alert(ses, torrent_deleted_alert::alert_type); + alert const* da = wait_for_alert(ses, torrent_deleted_alert::alert_type); + TEST_CHECK(da); } TEST_CHECK(!exists(combine_path(test_path, combine_path("tmp1", "temporary")))); if (exists(combine_path(test_path, combine_path("tmp1", "temporary")))) @@ -679,23 +680,10 @@ void test_fastresume(std::string const& test_path) bencode(std::back_inserter(p.resume_data), resume); torrent_handle h = ses.add_torrent(p, ec); - std::auto_ptr a = ses.pop_alert(); - time_point end = clock_type::now() + seconds(20); - while (clock_type::now() < end - && (a.get() == 0 - || alert_cast(a.get()) == 0)) - { - if (ses.wait_for_alert(end - clock_type::now()) == 0) - { - std::cerr << "wait_for_alert() expired" << std::endl; - break; - } - a = ses.pop_alert(); - assert(a.get()); - std::cerr << a->message() << std::endl; - } + alert const* a = wait_for_alert(ses, fastresume_rejected_alert::alert_type + , "ses"); // we expect the fast resume to be rejected because the files were removed - TEST_CHECK(alert_cast(a.get()) != 0); + TEST_CHECK(alert_cast(a) != 0); } remove_all(combine_path(test_path, "tmp1"), ec); if (ec && ec != boost::system::errc::no_such_file_or_directory) @@ -703,7 +691,7 @@ void test_fastresume(std::string const& test_path) << "': " << ec.message() << std::endl; } -bool got_file_rename_alert(alert* a) +bool got_file_rename_alert(alert const* a) { return alert_cast(a) || alert_cast(a); @@ -752,9 +740,9 @@ void test_rename_file_in_fastresume(std::string const& test_path) TEST_CHECK(s.state == torrent_status::seeding); h.save_resume_data(); - std::auto_ptr ra = wait_for_alert(ses, save_resume_data_alert::alert_type); - TEST_CHECK(ra.get()); - if (ra.get()) resume = *alert_cast(ra.get())->resume_data; + alert const* ra = wait_for_alert(ses, save_resume_data_alert::alert_type); + TEST_CHECK(ra); + if (ra) resume = *alert_cast(ra)->resume_data; ses.remove_torrent(h); } TEST_CHECK(!exists(combine_path(test_path, "tmp2/temporary"))); @@ -789,9 +777,9 @@ void test_rename_file_in_fastresume(std::string const& test_path) TEST_CHECK(stat.state == torrent_status::seeding); h.save_resume_data(); - std::auto_ptr ra = wait_for_alert(ses, save_resume_data_alert::alert_type); - TEST_CHECK(ra.get()); - if (ra.get()) resume = *alert_cast(ra.get())->resume_data; + alert const* ra = wait_for_alert(ses, save_resume_data_alert::alert_type); + TEST_CHECK(ra); + if (ra) resume = *alert_cast(ra)->resume_data; ses.remove_torrent(h); } TEST_CHECK(resume.dict().find("mapped_files") != resume.dict().end()); diff --git a/test/test_torrent.cpp b/test/test_torrent.cpp index 81cb782ad..3e91de1e6 100644 --- a/test/test_torrent.cpp +++ b/test/test_torrent.cpp @@ -137,27 +137,18 @@ void test_running_torrent(boost::shared_ptr info, boost::int64_t f std::cout << "reading piece 0" << std::endl; h.read_piece(0); - alert const* a = ses.wait_for_alert(seconds(10)); - bool passed = false; - while (a) + alert const* a = wait_for_alert(ses, read_piece_alert::alert_type, "read_piece"); + TEST_CHECK(a); + read_piece_alert const* rpa = alert_cast(a); + TEST_CHECK(rpa); + if (rpa) { - std::auto_ptr al = ses.pop_alert(); - assert(al.get()); - std::cout << " " << al->message() << std::endl; - if (read_piece_alert* rpa = alert_cast(al.get())) - { - std::cout << "SUCCEEDED!" << std::endl; - passed = true; - TEST_CHECK(memcmp(&piece[0], rpa->buffer.get(), piece.size()) == 0); - TEST_CHECK(rpa->size == info->piece_size(0)); - TEST_CHECK(rpa->piece == 0); - TEST_CHECK(hasher(&piece[0], piece.size()).final() == info->hash_for_piece(0)); - break; - } - a = ses.wait_for_alert(seconds(10)); - TEST_CHECK(a); + std::cout << "SUCCEEDED!" << std::endl; + TEST_CHECK(memcmp(&piece[0], rpa->buffer.get(), piece.size()) == 0); + TEST_CHECK(rpa->size == info->piece_size(0)); + TEST_CHECK(rpa->piece == 0); + TEST_CHECK(hasher(&piece[0], piece.size()).final() == info->hash_for_piece(0)); } - TEST_CHECK(passed); } } diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index 410ef1c69..fd77c61e9 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -57,7 +57,7 @@ int peer_disconnects = 0; int tracker_responses = 0; -bool on_alert(alert* a) +bool on_alert(alert const* a) { if (alert_cast(a)) ++tracker_responses; diff --git a/test/web_seed_suite.cpp b/test/web_seed_suite.cpp index 94afe8a68..ac70abad7 100644 --- a/test/web_seed_suite.cpp +++ b/test/web_seed_suite.cpp @@ -56,7 +56,7 @@ namespace lt = libtorrent; int peer_disconnects = 0; -bool on_alert(alert* a) +bool on_alert(alert const* a) { if (alert_cast(a)) ++peer_disconnects; diff --git a/tools/dht_put.cpp b/tools/dht_put.cpp index 6c7015fb8..4a32cd9d1 100644 --- a/tools/dht_put.cpp +++ b/tools/dht_put.cpp @@ -73,17 +73,17 @@ void usage() exit(1); } -std::auto_ptr wait_for_alert(lt::session& s, int alert_type) +alert* wait_for_alert(lt::session& s, int alert_type) { - std::auto_ptr ret; + alert* ret = NULL; bool found = false; while (!found) { s.wait_for_alert(seconds(5)); - std::deque alerts; + std::vector alerts; s.pop_alerts(&alerts); - for (std::deque::iterator i = alerts.begin() + for (std::vector::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { if ((*i)->type() != alert_type) @@ -94,10 +94,9 @@ std::auto_ptr wait_for_alert(lt::session& s, int alert_type) fflush(stdout); spinner = (spinner + 1) & 3; //print some alerts? - delete *i; continue; } - ret = std::auto_ptr(*i); + ret = *i; found = true; } } @@ -214,9 +213,9 @@ int main(int argc, char* argv[]) printf("GET %s\n", to_hex(target.to_string()).c_str()); - std::auto_ptr a = wait_for_alert(s, dht_immutable_item_alert::alert_type); + alert* a = wait_for_alert(s, dht_immutable_item_alert::alert_type); - dht_immutable_item_alert* item = alert_cast(a.get()); + dht_immutable_item_alert* item = alert_cast(a); entry data; if (item) data.swap(item->item); @@ -298,9 +297,9 @@ int main(int argc, char* argv[]) bootstrap(s); s.dht_get_item(public_key); - std::auto_ptr a = wait_for_alert(s, dht_mutable_item_alert::alert_type); + alert* a = wait_for_alert(s, dht_mutable_item_alert::alert_type); - dht_mutable_item_alert* item = alert_cast(a.get()); + dht_mutable_item_alert* item = alert_cast(a); entry data; if (item) data.swap(item->item); diff --git a/tools/test_coverage.sh b/tools/test_coverage.sh index f0e81581c..ea1cc8c00 100755 --- a/tools/test_coverage.sh +++ b/tools/test_coverage.sh @@ -34,6 +34,7 @@ set +e mkdir test-coverage set -e +run_test test_heterogeneous_queue "include/libtorrent/heterogeneous_queue.hpp" run_test test_dht "*/kademlia/*" run_test test_bdecode "*/bdecode.*" run_test test_piece_picker "*/piece_picker.*"