From 58d93e5aa17a029fc817215841299ea9723549c3 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 17 Jan 2015 17:02:58 +0000 Subject: [PATCH] add new (non-deprecated) access to dht stats, asynchronously via an alert --- examples/client_test.cpp | 30 +++++-- include/libtorrent/alert_types.hpp | 81 ++++++++++++++++++- include/libtorrent/aux_/session_impl.hpp | 1 + include/libtorrent/kademlia/dht_tracker.hpp | 4 + include/libtorrent/kademlia/node.hpp | 4 + include/libtorrent/kademlia/routing_table.hpp | 7 +- include/libtorrent/performance_counters.hpp | 3 + include/libtorrent/session.hpp | 3 + include/libtorrent/session_status.hpp | 63 ++------------- src/alert.cpp | 9 +++ src/kademlia/dht_tracker.cpp | 6 ++ src/kademlia/node.cpp | 17 ++++ src/kademlia/routing_table.cpp | 14 ++++ src/session.cpp | 5 ++ src/session_impl.cpp | 12 +++ 15 files changed, 190 insertions(+), 69 deletions(-) diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 15c31ccc6..97195a3ac 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -180,6 +180,11 @@ bool print_disk_stats = false; // without having received a response (successful or failure) int num_outstanding_resume_data = 0; +#ifndef TORRENT_DISABLE_DHT +std::vector dht_active_requests; +std::vector dht_routing_table; +#endif + torrent_view view; session_view ses_view; @@ -905,6 +910,14 @@ bool handle_alert(libtorrent::session& ses, libtorrent::alert* a ses_view.update_counters(s->values, s->timestamp); 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->dht_routing_table); + } +#endif #ifdef TORRENT_USE_OPENSSL if (torrent_need_cert_alert* p = alert_cast(a)) @@ -953,6 +966,7 @@ bool handle_alert(libtorrent::session& ses, libtorrent::alert* a } #endif + if (metadata_received_alert* p = alert_cast(a)) { // if we have a monitor dir, save the .torrent file we just received in it @@ -1618,6 +1632,7 @@ int main(int argc, char* argv[]) ++tick; ses.post_torrent_updates(); ses.post_session_stats(); + ses.post_dht_stats(); int terminal_width = 80; int terminal_height = 50; @@ -1951,20 +1966,20 @@ int main(int argc, char* argv[]) cache_status cs; ses.get_cache_info(&cs, h, cache_flags); - // TODO: 3 introce some reasonable way of getting DHT stats -/* #ifndef TORRENT_DISABLE_DHT if (show_dht_status) { + // TODO: 3 expose these counters as performance counters +/* snprintf(str, sizeof(str), "DHT nodes: %d DHT cached nodes: %d " "total DHT size: %" PRId64 " total observers: %d\n" , sess_stat.dht_nodes, sess_stat.dht_node_cache, sess_stat.dht_global_nodes , sess_stat.dht_total_allocations); out += str; - +*/ int bucket = 0; - for (std::vector::iterator i = sess_stat.dht_routing_table.begin() - , end(sess_stat.dht_routing_table.end()); i != end; ++i, ++bucket) + for (std::vector::iterator i = dht_routing_table.begin() + , end(dht_routing_table.end()); i != end; ++i, ++bucket) { char const* progress_bar = "################################" @@ -1980,8 +1995,8 @@ int main(int argc, char* argv[]) out += str; } - for (std::vector::iterator i = sess_stat.active_requests.begin() - , end(sess_stat.active_requests.end()); i != end; ++i) + for (std::vector::iterator i = dht_active_requests.begin() + , end(dht_active_requests.end()); i != end; ++i) { snprintf(str, sizeof(str) , " %10s [limit: %2d] " @@ -2003,7 +2018,6 @@ int main(int argc, char* argv[]) } } #endif -*/ if (h.is_valid()) { torrent_status const& s = view.get_active_torrent(); diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index ca5fb4256..f9eb8f05a 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -2266,9 +2266,88 @@ namespace libtorrent error_code error; }; + // holds statistics about a current dht_lookup operation. + // a DHT lookup is the travesal of nodes, looking up a + // set of target nodes in the DHT for retrieving and possibly + // storing information in the DHT + struct TORRENT_EXPORT dht_lookup + { + // string literal indicating which kind of lookup this is + char const* type; + + // the number of outstanding request to individual nodes + // this lookup has right now + int outstanding_requests; + + // the total number of requests that have timed out so far + // for this lookup + int timeouts; + + // the total number of responses we have received for this + // lookup so far for this lookup + int responses; + + // the branch factor for this lookup. This is the number of + // nodes we keep outstanding requests to in parallel by default. + // when nodes time out we may increase this. + int branch_factor; + + // the number of nodes left that could be queries for this + // lookup. Many of these are likely to be part of the trail + // while performing the lookup and would never end up actually + // being queried. + int nodes_left; + + // the number of seconds ago the + // last message was sent that's still + // outstanding + int last_sent; + + // the number of outstanding requests + // that have exceeded the short timeout + // and are considered timed out in the + // sense that they increased the branch + // factor + int first_timeout; + }; + + // struct to hold information about a single DHT routing table bucket + struct TORRENT_EXPORT dht_routing_bucket + { + // the total number of nodes and replacement nodes + // in the routing table + int num_nodes; + int num_replacements; + + // number of seconds since last activity + int last_active; + }; + + // contains current DHT state. Posted in response to session::post_dht_stats(). + struct TORRENT_EXPORT dht_stats_alert : alert + { + // internal + dht_stats_alert() + : alert() + {} + + TORRENT_DEFINE_ALERT(dht_stats_alert, 83); + + const static int static_category = alert::stats_notification; + virtual std::string message() const; + + // a vector of the currently running DHT lookups. + std::vector active_requests; + + // contains information about every bucket in the DHT routing + // table. + std::vector dht_routing_table; + }; + + #undef TORRENT_DEFINE_ALERT - enum { num_alert_types = 83 }; + enum { num_alert_types = 84 }; } diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index bca9a54da..d5e75b428 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -417,6 +417,7 @@ namespace libtorrent , boost::uint32_t flags) const; void post_torrent_updates(); void post_session_stats(); + void post_dht_stats(); std::vector get_torrents() const; diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index e5ef938c8..9774a6dbb 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -73,6 +73,7 @@ namespace libtorrent { namespace dht struct dht_tracker; + // TODO: 3 remove these TORRENT_EXTRA_EXPORT void intrusive_ptr_add_ref(dht_tracker const*); TORRENT_EXTRA_EXPORT void intrusive_ptr_release(dht_tracker const*); @@ -117,6 +118,8 @@ namespace libtorrent { namespace dht #ifndef TORRENT_NO_DEPRECATE void dht_status(session_status& s); #endif + void dht_status(std::vector& table + , std::vector& requests); void network_stats(int& sent, int& received); @@ -163,6 +166,7 @@ namespace libtorrent { namespace dht udp::resolver m_host_resolver; // sent and received bytes since queried last time + // TODO: 3 these members are probably unnecessary int m_sent_bytes; int m_received_bytes; diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index c68041544..fe2bfdd6b 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -61,6 +61,7 @@ namespace libtorrent { struct alert_dispatcher; class alert; struct counters; + struct dht_routing_bucket; } namespace libtorrent { namespace dht @@ -275,6 +276,9 @@ public: m_running_requests.erase(a); } + void status(std::vector& table + , std::vector& requests); + #ifndef TORRENT_NO_DEPRECATE void status(libtorrent::session_status& s); #endif diff --git a/include/libtorrent/kademlia/routing_table.hpp b/include/libtorrent/kademlia/routing_table.hpp index 07a9c019f..7a9911a9e 100644 --- a/include/libtorrent/kademlia/routing_table.hpp +++ b/include/libtorrent/kademlia/routing_table.hpp @@ -51,12 +51,13 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#ifndef TORRENT_NO_DEPRECATE namespace libtorrent { +#ifndef TORRENT_NO_DEPRECATE struct session_status; -} #endif + struct dht_routing_bucket; +} namespace libtorrent { namespace dht { @@ -96,6 +97,8 @@ public: void status(session_status& s) const; #endif + void status(std::vector& s) const; + void node_failed(node_id const& id, udp::endpoint const& ep); // adds an endpoint that will never be added to diff --git a/include/libtorrent/performance_counters.hpp b/include/libtorrent/performance_counters.hpp index fc7c91eeb..d743879c5 100644 --- a/include/libtorrent/performance_counters.hpp +++ b/include/libtorrent/performance_counters.hpp @@ -227,6 +227,9 @@ namespace libtorrent dht_get_out, dht_put_in, dht_put_out, + + // TODO: 3 these counters are redundant with dht_bytes_in and dht_bytes_out + // remove them sent_dht_bytes, recv_dht_bytes, diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 1f6ff895a..3914ec8b0 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -365,6 +365,9 @@ namespace libtorrent // For more information, see the session-statistics_ section. void post_session_stats(); + // This will cause a dht_stats_alert to be posted. + void post_dht_stats(); + // internal io_service& get_io_service(); diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index 16d7cdf66..854c8b2b9 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -36,67 +36,14 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include +#ifndef TORRENT_NO_DEPRECATE +// for dht_lookup and dht_routing_bucket +#include "libtorrent/alert_types.hpp" +#endif + namespace libtorrent { - // holds statistics about a current dht_lookup operation. - // a DHT lookup is the travesal of nodes, looking up a - // set of target nodes in the DHT for retrieving and possibly - // storing information in the DHT - struct TORRENT_EXPORT dht_lookup - { - // string literal indicating which kind of lookup this is - char const* type; - - // the number of outstanding request to individual nodes - // this lookup has right now - int outstanding_requests; - - // the total number of requests that have timed out so far - // for this lookup - int timeouts; - - // the total number of responses we have received for this - // lookup so far for this lookup - int responses; - - // the branch factor for this lookup. This is the number of - // nodes we keep outstanding requests to in parallel by default. - // when nodes time out we may increase this. - int branch_factor; - - // the number of nodes left that could be queries for this - // lookup. Many of these are likely to be part of the trail - // while performing the lookup and would never end up actually - // being queried. - int nodes_left; - - // the number of seconds ago the - // last message was sent that's still - // outstanding - int last_sent; - - // the number of outstanding requests - // that have exceeded the short timeout - // and are considered timed out in the - // sense that they increased the branch - // factor - int first_timeout; - }; - - // TODO: 3 add accessors to query the DHT state (post the result as an alert) - // holds dht routing table stats - struct TORRENT_EXPORT dht_routing_bucket - { - // the total number of nodes and replacement nodes - // in the routing table - int num_nodes; - int num_replacements; - - // number of seconds since last activity - int last_active; - }; - #ifndef TORRENT_NO_DEPRECATE // holds counters and gauges for the uTP sockets // deprecated in 1.1 in favor of session_stats counters, which is a more diff --git a/src/alert.cpp b/src/alert.cpp index 96d779f16..9a17da756 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -735,5 +735,14 @@ namespace libtorrent { return "Local Service Discovery error: " + error.message(); } + std::string dht_stats_alert::message() const + { + char buf[2048]; + snprintf(buf, sizeof(buf), "DHT stats: reqs: %d buckets: %d" + , int(active_requests.size()) + , int(dht_routing_table.size())); + return buf; + } + } // namespace libtorrent diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 419647d07..0c01d0f2c 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -266,6 +266,12 @@ namespace libtorrent { namespace dht } #endif + void dht_tracker::dht_status(std::vector& table + , std::vector& requests) + { + m_dht.status(table, requests); + } + void dht_tracker::network_stats(int& sent, int& received) { sent = m_sent_bytes; diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 1d9908df5..7390fcc99 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -565,7 +565,24 @@ time_duration node_impl::connection_timeout() return d; } +void node_impl::status(std::vector& table + , std::vector& requests) +{ + mutex_t::scoped_lock l(m_mutex); + + m_table.status(table); + + for (std::set::iterator i = m_running_requests.begin() + , end(m_running_requests.end()); i != end; ++i) + { + requests.push_back(dht_lookup()); + dht_lookup& l = requests.back(); + (*i)->status(l); + } +} + #ifndef TORRENT_NO_DEPRECATE +// TODO: 2 use the non deprecated function instead of this one void node_impl::status(session_status& s) { mutex_t::scoped_lock l(m_mutex); diff --git a/src/kademlia/routing_table.cpp b/src/kademlia/routing_table.cpp index 8437857c6..cbfcb97db 100644 --- a/src/kademlia/routing_table.cpp +++ b/src/kademlia/routing_table.cpp @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session_status.hpp" #include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/time.hpp" +#include "libtorrent/alert_types.hpp" // for dht_routing_bucket #include "libtorrent/invariant_check.hpp" @@ -93,7 +94,20 @@ int routing_table::bucket_limit(int bucket) const return m_bucket_size; } +void routing_table::status(std::vector& s) const +{ + for (table_t::const_iterator i = m_buckets.begin() + , end(m_buckets.end()); i != end; ++i) + { + dht_routing_bucket b; + b.num_nodes = i->live_nodes.size(); + b.num_replacements = i->replacements.size(); + s.push_back(b); + } +} + #ifndef TORRENT_NO_DEPRECATE +// TODO: 2 use the non deprecated function instead of this one void routing_table::status(session_status& s) const { int ignore; diff --git a/src/session.cpp b/src/session.cpp index 693fbfdd9..6723cc71b 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -587,6 +587,11 @@ namespace libtorrent TORRENT_ASYNC_CALL(post_session_stats); } + void session::post_dht_stats() + { + TORRENT_ASYNC_CALL(post_dht_stats); + } + std::vector session::get_torrents() const { return TORRENT_SYNC_CALL_RET(std::vector, get_torrents); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 68932884f..779c489e1 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -4395,6 +4395,18 @@ retry: m_alerts.post_alert_ptr(alert.release()); } + void session_impl::post_dht_stats() + { + std::auto_ptr alert(new dht_stats_alert()); + +#ifndef TORRENT_DISABLE_DHT + if (m_dht) + m_dht->dht_status(alert->dht_routing_table, alert->active_requests); +#endif + + m_alerts.post_alert_ptr(alert.release()); + } + std::vector session_impl::get_torrents() const { std::vector ret;