added stats_alert reporting raw transfer stats per torrent every second

This commit is contained in:
Arvid Norberg 2010-01-02 14:16:35 +00:00
parent 33c98c00f7
commit cbf2526a8c
8 changed files with 190 additions and 31 deletions

View File

@ -307,20 +307,20 @@ void bind_alert()
class_<torrent_resumed_alert, bases<torrent_alert>, noncopyable>(
"torrent_resumed_alert", no_init
);
);
class_<state_changed_alert, bases<torrent_alert>, noncopyable>(
"state_changed_alert", no_init
)
.def_readonly("state", &state_changed_alert::state)
.def_readonly("prev_state", &state_changed_alert::prev_state)
;
class_<state_changed_alert, bases<torrent_alert>, noncopyable>(
"state_changed_alert", no_init
)
.def_readonly("state", &state_changed_alert::state)
.def_readonly("prev_state", &state_changed_alert::prev_state)
;
class_<dht_reply_alert, bases<tracker_alert>, noncopyable>(
"dht_reply_alert", no_init
)
.def_readonly("num_peers", &dht_reply_alert::num_peers)
;
class_<dht_reply_alert, bases<tracker_alert>, noncopyable>(
"dht_reply_alert", no_init
)
.def_readonly("num_peers", &dht_reply_alert::num_peers)
;
class_<dht_announce_alert, bases<alert>, noncopyable>(
"dht_announce_alert", no_init
@ -336,13 +336,13 @@ void bind_alert()
.def_readonly("info_hash", &dht_get_peers_alert::info_hash)
;
class_<peer_unsnubbed_alert, bases<peer_alert>, noncopyable>(
"peer_unsnubbed_alert", no_init
);
class_<peer_unsnubbed_alert, bases<peer_alert>, noncopyable>(
"peer_unsnubbed_alert", no_init
);
class_<peer_snubbed_alert, bases<peer_alert>, noncopyable>(
"peer_snubbed_alert", no_init
);
class_<peer_snubbed_alert, bases<peer_alert>, noncopyable>(
"peer_snubbed_alert", no_init
);
class_<peer_connect_alert, bases<peer_alert>, noncopyable>(
"peer_connect_alert", no_init
@ -406,5 +406,24 @@ void bind_alert()
;
class_<stats_alert, bases<torrent_alert>, noncopyable>(
"stats_alert", no_init
)
.def_readonly("transferred", &stats_alert::transferred)
.def_readonly("interval", &stats_alert::interval)
;
enum_<stats_alert::stats_channel>("stats_channel")
.value("upload_payload", stats_alert::upload_payload)
.value("upload_protocol", stats_alert::upload_protocol)
.value("upload_ip_protocol", stats_alert::upload_ip_protocol)
.value("upload_dht_protocol", stats_alert::upload_dht_protocol)
.value("upload_tracker_protocol", stats_alert::upload_tracker_protocol)
.value("download_payload", stats_alert::download_payload)
.value("download_protocol", stats_alert::download_protocol)
.value("download_ip_protocol", stats_alert::download_ip_protocol)
.value("download_dht_protocol", stats_alert::download_dht_protocol)
.value("download_tracker_protocol", stats_alert::download_tracker_protocol)
;
}

View File

@ -4748,6 +4748,11 @@ is a bitmask with the following bits:
| ``performance_warning`` | Alerts when some limit is reached that might limit the download |
| | or upload rate. |
+--------------------------------+---------------------------------------------------------------------+
| ``stats_notification`` | If you enable these alerts, you will receive a ``stats_alert`` |
| | approximately once every second, for every active torrent. |
| | These alerts contain all statistics counters for the interval since |
| | the lasts stats alert. |
+--------------------------------+---------------------------------------------------------------------+
| ``all_categories`` | The full bitmask, representing all available categories. |
+--------------------------------+---------------------------------------------------------------------+
@ -5646,6 +5651,45 @@ generating the resume data. ``error`` describes what went wrong.
error_code error;
};
stats_alert
-----------
This alert is posted approximately once every second, and it contains
byte counters of most statistics that's tracked for torrents. Each active
torrent posts these alerts regularly.
::
struct stats_alert: torrent_alert
{
// ...
enum stats_channel
{
upload_payload,
upload_protocol,
upload_ip_protocol,
upload_dht_protocol,
upload_tracker_protocol,
download_payload,
download_protocol,
download_ip_protocol,
download_dht_protocol,
download_tracker_protocol,
num_channels
};
int transferred[num_channels];
int interval;
};
``transferred`` this is an array of samples. The enum describes what each
sample is a measurement of. All of these are raw, and not smoothing is performed.
``interval`` the number of milliseconds during which these stats
were collected. This is typically just above 1000, but if CPU is
limited, it may be higher than that.
dht_announce_alert
------------------

View File

@ -86,6 +86,7 @@ namespace libtorrent {
ip_block_notification = 0x100,
performance_warning = 0x200,
dht_notification = 0x400,
stats_notification = 0x800,
all_categories = 0xffffffff
};

View File

@ -40,6 +40,16 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/assert.hpp"
#include "libtorrent/identify_client.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/stat.hpp"
// lines reserved for future includes
// the type-ids of the alert types
// are derived from the line on which
// they are declared
namespace libtorrent
{
@ -1078,6 +1088,36 @@ namespace libtorrent
sha1_hash info_hash;
};
struct TORRENT_EXPORT stats_alert: torrent_alert
{
stats_alert(torrent_handle const& h, int interval
, stat const& s);
TORRENT_DEFINE_ALERT(stats_alert);
const static int static_category = alert::stats_notification;
virtual std::string message() const;
enum stats_channel
{
upload_payload,
upload_protocol,
upload_ip_protocol,
upload_dht_protocol,
upload_tracker_protocol,
download_payload,
download_protocol,
download_ip_protocol,
download_dht_protocol,
download_tracker_protocol,
num_channels
};
int transferred[num_channels];
int interval;
};
}

View File

@ -52,13 +52,16 @@ namespace libtorrent
enum { history = 10 };
stat_channel()
: m_counter(0)
: m_window(3)
, m_counter(0)
, m_total_counter(0)
, m_rate_sum(0)
{
std::memset(m_rate_history, 0, sizeof(m_rate_history));
}
void set_window(int w);
void operator+=(stat_channel const& s)
{
TORRENT_ASSERT(m_counter >= 0);
@ -82,7 +85,7 @@ namespace libtorrent
// should be called once every second
void second_tick(int tick_interval_ms);
int rate() const { return int(m_rate_sum / history); }
int rate() const { return int(m_rate_sum / m_window); }
size_type rate_sum() const { return m_rate_sum; }
size_type total() const { return m_total_counter; }
@ -104,13 +107,15 @@ namespace libtorrent
m_rate_sum = 0;
}
int window() const { return m_window; }
private:
#ifdef TORRENT_DEBUG
void check_invariant() const
{
size_type sum = 0;
for (int i = 0; i < history; ++i) sum += m_rate_history[i];
for (int i = 0; i < m_window; ++i) sum += m_rate_history[i];
TORRENT_ASSERT(m_rate_sum == sum);
TORRENT_ASSERT(m_total_counter >= 0);
}
@ -119,6 +124,9 @@ namespace libtorrent
// history of rates a few seconds back
int m_rate_history[history];
// averaging window (seconds). 'history' is the max size
int m_window;
// the accumulator for this second.
int m_counter;
@ -216,6 +224,12 @@ namespace libtorrent
int download_tracker() const { return m_stat[download_tracker_protocol].counter(); }
int upload_tracker() const { return m_stat[upload_tracker_protocol].counter(); }
void set_window(int w)
{
for (int i = 0; i < num_channels; ++i)
m_stat[i].set_window(w);
}
// should be called once every second
void second_tick(int tick_interval_ms)
{
@ -229,7 +243,7 @@ namespace libtorrent
+ m_stat[upload_protocol].rate_sum()
+ m_stat[upload_ip_protocol].rate_sum()
+ m_stat[upload_dht_protocol].rate_sum())
/ stat_channel::history);
/ m_stat[0].window());
}
int download_rate() const
@ -238,7 +252,7 @@ namespace libtorrent
+ m_stat[download_protocol].rate_sum()
+ m_stat[download_ip_protocol].rate_sum()
+ m_stat[download_dht_protocol].rate_sum())
/ stat_channel::history);
/ m_stat[0].window());
}
size_type total_upload() const
@ -319,6 +333,12 @@ namespace libtorrent
m_stat[i].clear();
}
stat_channel const& operator[](int i) const
{
TORRENT_ASSERT(i >= 0 && i < num_channels);
return m_stat[i];
}
private:
stat_channel m_stat[num_channels];

View File

@ -433,5 +433,33 @@ namespace libtorrent {
return queue_size_limit_;
}
stats_alert::stats_alert(torrent_handle const& h, int in
, stat const& s)
: torrent_alert(h)
, interval(in)
{
for (int i = 0; i < num_channels; ++i)
transferred[i] = s[i].counter();
}
std::string stats_alert::message() const
{
char msg[200];
snprintf(msg, sizeof(msg), "%s: [%d] %d %d %d %d %d %d %d %d %d %d"
, torrent_alert::message().c_str()
, interval
, transferred[0]
, transferred[1]
, transferred[2]
, transferred[3]
, transferred[4]
, transferred[5]
, transferred[6]
, transferred[7]
, transferred[8]
, transferred[9]);
return msg;
}
} // namespace libtorrent

View File

@ -30,11 +30,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/
// TODO: Use two algorithms to estimate transfer rate.
// one (simple) for transfer rates that are >= 1 packet
// per second and one (low pass-filter) for rates < 1
// packet per second.
#include "libtorrent/pch.hpp"
#include <numeric>
@ -43,14 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/stat.hpp"
#include "libtorrent/invariant_check.hpp"
namespace libtorrent
{
namespace libtorrent {
void stat_channel::second_tick(int tick_interval_ms)
{
INVARIANT_CHECK;
m_rate_sum -= m_rate_history[history-1];
m_rate_sum -= m_rate_history[m_window-1];
for (int i = history - 2; i >= 0; --i)
m_rate_history[i + 1] = m_rate_history[i];
@ -61,6 +55,16 @@ void stat_channel::second_tick(int tick_interval_ms)
m_counter = 0;
}
void stat_channel::set_window(int w)
{
if (w < 1) w = 1;
else if (w > history) w = history;
m_window = w;
m_rate_sum = 0;
for (int i = 0; i < m_window; ++i)
m_rate_sum += m_rate_history[i];
}
}

View File

@ -5456,6 +5456,9 @@ namespace libtorrent
}
#endif
}
if (m_ses.m_alerts.should_post<stats_alert>())
m_ses.m_alerts.post_alert(stats_alert(get_handle(), tick_interval_ms, m_stat));
accumulator += m_stat;
m_total_uploaded += m_stat.last_payload_uploaded();
m_total_downloaded += m_stat.last_payload_downloaded();