more work towards making client_test event-driven and use session stats counters instead of session_status + some refactoring

This commit is contained in:
Arvid Norberg 2014-07-08 22:37:13 +00:00
parent 9d172a8723
commit 8fc07e6e89
8 changed files with 223 additions and 133 deletions

View File

@ -16,7 +16,7 @@ project client_test
<link>static
;
exe client_test : client_test.cpp print.cpp torrent_view.cpp ;
exe client_test : client_test.cpp print.cpp torrent_view.cpp session_view.cpp ;
exe simple_client : simple_client.cpp ;
exe stats_counters : stats_counters.cpp ;

View File

@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/create_torrent.hpp"
#include "torrent_view.hpp"
#include "session_view.hpp"
#include "print.hpp"
using boost::bind;
@ -177,8 +178,10 @@ bool print_disk_stats = false;
int num_outstanding_resume_data = 0;
torrent_view view;
session_view ses_view;
int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
int load_file(std::string const& filename, std::vector<char>& v
, libtorrent::error_code& ec, int limit = 8000000)
{
ec.clear();
FILE* f = fopen(filename.c_str(), "rb");
@ -735,14 +738,13 @@ int save_file(std::string const& filename, std::vector<char>& v)
// returns true if the alert was handled (and should not be printed to the log)
// returns false if the alert was not handled
bool handle_alert(libtorrent::session& ses, libtorrent::alert* a
, handles_t& files, std::set<libtorrent::torrent_handle>& non_files
, std::vector<boost::uint64_t>& stats_counters)
, handles_t& files, std::set<libtorrent::torrent_handle>& non_files)
{
using namespace libtorrent;
if (session_stats_alert* s = alert_cast<session_stats_alert>(a))
{
stats_counters.swap(s->values);
ses_view.update_counters(s->values, s->timestamp);
return true;
}
@ -1079,12 +1081,6 @@ int main(int argc, char* argv[])
settings_pack settings;
settings.set_int(settings_pack::active_loaded_limit, 20);
std::vector<boost::uint64_t> stats_counters;
std::vector<stats_metric> metrics = session_stats_metrics();
stats_counters.resize(metrics.size(), 0);
const int queued_bytes_idx = find_metric_idx(metrics, "queued_write_bytes");
proxy_settings ps;
int refresh_delay = 500;
@ -1436,18 +1432,24 @@ int main(int argc, char* argv[])
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
#endif
while (!quit)
{
++tick;
ses.post_torrent_updates();
ses.post_session_stats();
int c = 0;
int terminal_width = 80;
int terminal_height = 50;
terminal_size(&terminal_width, &terminal_height);
view.set_size(terminal_width, terminal_height / 2);
ses_view.set_pos(terminal_height / 2);
int c = 0;
if (sleep_and_input(&c, refresh_delay))
{
#ifdef WIN32
#ifdef _WIN32
#define ESCAPE_SEQ 224
#define LEFT_ARROW 75
#define RIGHT_ARROW 77
@ -1587,11 +1589,6 @@ int main(int argc, char* argv[])
h.force_recheck();
}
if (c == 'x')
{
print_disk_stats = !print_disk_stats;
}
if (c == 'r' && h.is_valid())
{
h.force_reannounce();
@ -1672,6 +1669,7 @@ int main(int argc, char* argv[])
if (c == 'a') print_piece_bar = !print_piece_bar;
if (c == 'g') show_dht_status = !show_dht_status;
if (c == 'u') print_utp_stats = !print_utp_stats;
if (c == 'x') print_disk_stats = !print_disk_stats;
// toggle columns
if (c == '1') print_ip = !print_ip;
if (c == '2') print_as = !print_as;
@ -1716,17 +1714,11 @@ int main(int argc, char* argv[])
int tmp;
while (sleep_and_input(&tmp, 500) == false);
}
} while (sleep_and_input(&c, 0));
if (c == 'q') break;
}
int terminal_width = 80;
int terminal_height = 50;
terminal_size(&terminal_width, &terminal_height);
view.set_max_size(terminal_height - 15);
// loop through the alert queue to see if anything has happened.
std::deque<alert*> alerts;
ses.pop_alerts(&alerts);
@ -1736,8 +1728,7 @@ int main(int argc, char* argv[])
{
TORRENT_TRY
{
if (!::handle_alert(ses, *i, files, non_files
, stats_counters))
if (!::handle_alert(ses, *i, files, non_files))
{
// if we didn't handle the alert, print it to the log
std::string event_string;
@ -1756,8 +1747,9 @@ int main(int argc, char* argv[])
char str[500];
clear_below(view.height());
set_cursor_pos(0, view.height());
int pos = view.height() + ses_view.height();
clear_rows(pos, terminal_height);
set_cursor_pos(0, pos);
int cache_flags = print_downloads ? 0 : lt::session::disk_cache_no_pieces;
torrent_handle h = view.get_active_handle();
@ -1768,44 +1760,6 @@ int main(int argc, char* argv[])
if (cs.blocks_read < 1) cs.blocks_read = 1;
if (cs.blocks_written < 1) cs.blocks_written = 1;
snprintf(str, sizeof(str), "==== conns: %d (%d) down: %s%s%s (%s%s%s) up: %s%s%s (%s%s%s) "
"tcp/ip: %s%s%s %s%s%s DHT: %s%s%s %s%s%s tracker: %s%s%s %s%s%s ====\n"
, sess_stat.num_peers, sess_stat.num_dead_peers
, esc("32"), add_suffix(sess_stat.download_rate, "/s").c_str(), esc("0")
, esc("32"), add_suffix(sess_stat.total_download).c_str(), esc("0")
, esc("31"), add_suffix(sess_stat.upload_rate, "/s").c_str(), esc("0")
, esc("31"), add_suffix(sess_stat.total_upload).c_str(), esc("0")
, esc("32"), add_suffix(sess_stat.ip_overhead_download_rate, "/s").c_str(), esc("0")
, esc("31"), add_suffix(sess_stat.ip_overhead_upload_rate, "/s").c_str(), esc("0")
, esc("32"), add_suffix(sess_stat.dht_download_rate, "/s").c_str(), esc("0")
, esc("31"), add_suffix(sess_stat.dht_upload_rate, "/s").c_str(), esc("0")
, esc("32"), add_suffix(sess_stat.tracker_download_rate, "/s").c_str(), esc("0")
, esc("31"), add_suffix(sess_stat.tracker_upload_rate, "/s").c_str(), esc("0"));
out += str;
snprintf(str, sizeof(str), "==== waste: %s fail: %s unchoked: %d / %d "
"bw queues: %8d (%d) | %8d (%d) disk queues: %d | %d cache: w: %d%% r: %d%% "
"size: w: %s r: %s total: %s ===\n"
, add_suffix(sess_stat.total_redundant_bytes).c_str()
, add_suffix(sess_stat.total_failed_bytes).c_str()
, sess_stat.num_unchoked, sess_stat.allowed_upload_slots
, sess_stat.up_bandwidth_bytes_queue
, sess_stat.up_bandwidth_queue
, sess_stat.down_bandwidth_bytes_queue
, sess_stat.down_bandwidth_queue
, sess_stat.disk_write_queue
, sess_stat.disk_read_queue
, int((cs.blocks_written - cs.writes) * 100 / cs.blocks_written)
, int(cs.blocks_read_hit * 100 / cs.blocks_read)
, add_suffix(boost::int64_t(cs.write_cache_size) * 16 * 1024).c_str()
, add_suffix(boost::int64_t(cs.read_cache_size) * 16 * 1024).c_str()
, add_suffix(boost::int64_t(cs.total_used_buffers) * 16 * 1024).c_str());
out += str;
snprintf(str, sizeof(str), "==== optimistic unchoke: %d unchoke counter: %d peerlist: %d ====\n"
, sess_stat.optimistic_unchoke_counter, sess_stat.unchoke_counter, sess_stat.peerlist_size);
out += str;
#ifndef TORRENT_DISABLE_DHT
if (show_dht_status)
{
@ -1848,51 +1802,6 @@ int main(int argc, char* argv[])
}
}
#endif
if (print_disk_stats)
{
snprintf(str, sizeof(str), "Disk stats:\n timing - "
" read: %6d ms | write: %6d ms | hash: %6d\n"
, cs.average_read_time / 1000, cs.average_write_time / 1000
, cs.average_hash_time / 1000);
out += str;
snprintf(str, sizeof(str), " jobs - queued: %4d (%4d) pending: %4d blocked: %4d "
"queued-bytes: %5" PRId64 " kB\n"
, cs.queued_jobs, cs.peak_queued, cs.pending_jobs, cs.blocked_jobs
, stats_counters[queued_bytes_idx] / 1000);
out += str;
snprintf(str, sizeof(str), " cache - total: %4d read: %4d write: %4d pinned: %4d write-queue: %4d\n"
, cs.read_cache_size + cs.write_cache_size, cs.read_cache_size, cs.write_cache_size, cs.pinned_blocks
, int(stats_counters[queued_bytes_idx] / 0x4000));
out += str;
int mru_size = cs.arc_mru_size + cs.arc_mru_ghost_size;
int mfu_size = cs.arc_mfu_size + cs.arc_mfu_ghost_size;
int arc_size = mru_size + mfu_size;
snprintf(str, sizeof(str), "LRU: (%d) %d LFU: %d (%d)\n"
, cs.arc_mru_ghost_size, cs.arc_mru_size
, cs.arc_mfu_size, cs.arc_mfu_ghost_size);
out += str;
if (arc_size > 0)
{
out += ' ';
if (mru_size > 0)
{
out += progress_bar(cs.arc_mru_ghost_size * 1000 / mru_size
, mru_size * (terminal_width-3) / arc_size, col_yellow, '-', '#');
}
out += '|';
if (mfu_size)
{
out += progress_bar(cs.arc_mfu_size * 1000 / mfu_size
, mfu_size * (terminal_width-3) / arc_size, col_green, '=', '-');
}
}
out += "\n";
}
if (print_utp_stats)
{
snprintf(str, sizeof(str), "uTP idle: %d syn: %d est: %d fin: %d wait: %d\n"
@ -1910,10 +1819,6 @@ int main(int argc, char* argv[])
|| print_peers)
h.get_peer_info(peers);
out += "====== ";
out += s.name;
out += " ======\n";
if (print_peers && !peers.empty())
print_peer_info(out, peers);

View File

@ -142,22 +142,25 @@ void clear_screen()
#endif
}
void clear_below(int y)
void clear_rows(int y1, int y2)
{
if (y1 > y2) return;
#ifdef _WIN32
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
COORD c = {0, y};
COORD c = {0, y1};
SetConsoleCursorPosition(out, c);
CONSOLE_SCREEN_BUFFER_INFO si;
GetConsoleScreenBufferInfo(out, &si);
DWORD n;
FillConsoleOutputCharacter(out, ' ', si.dwSize.X * (si.dwSize.Y - y), c, &n);
FillConsoleOutputAttribute(out, 0x7, si.dwSize.X * (si.dwSize.Y - y), c, &n);
int num_chars = si.dwSize.X * (std::min)(si.dwSize.Y - y1, y2 - y1);
FillConsoleOutputCharacter(out, ' ', num_chars, c, &n);
FillConsoleOutputAttribute(out, 0x7, num_chars, c, &n);
#else
printf("\033[%d;1H\033[J", y + 1);
for (int i = y1; i < y2; ++i)
printf("\033[%d;1H\033[2K", i + 1);
#endif
}
void terminal_size(int* terminal_width, int* terminal_height)

View File

@ -31,7 +31,7 @@ void set_cursor_pos(int x, int y);
void clear_screen();
void clear_below(int y);
void clear_rows(int y1, int y2);
void terminal_size(int* terminal_width, int* terminal_height);

168
examples/session_view.cpp Normal file
View File

@ -0,0 +1,168 @@
#include "session_view.hpp"
#include "print.hpp"
session_view::session_view()
{
std::vector<lt::stats_metric> metrics = lt::session_stats_metrics();
m_cnt[0].resize(metrics.size(), 0);
m_cnt[1].resize(metrics.size(), 0);
m_queued_bytes_idx = find_metric_idx(metrics, "disk.queued_write_bytes");
m_wasted_bytes_idx = find_metric_idx(metrics, "net.recv_redundant_bytes");
m_failed_bytes_idx = find_metric_idx(metrics, "net.recv_failed_bytes");
m_num_peers_idx = find_metric_idx(metrics, "peer.num_peers_connected");
m_recv_payload_idx = find_metric_idx(metrics, "net.recv_payload_bytes");
m_sent_payload_idx = find_metric_idx(metrics, "net.sent_payload_bytes");
m_unchoked_idx = find_metric_idx(metrics, "peer.num_peers_up_unchoked");
m_unchoke_slots_idx = find_metric_idx(metrics, "ses.num_unchoke_slots");
m_limiter_up_queue_idx = find_metric_idx(metrics, "net.limiter_up_queue");
m_limiter_down_queue_idx = find_metric_idx(metrics, "net.limiter_down_queue");
m_limiter_up_bytes_idx = find_metric_idx(metrics, "net.limiter_up_bytes");
m_limiter_down_bytes_idx = find_metric_idx(metrics, "net.limiter_down_bytes");
m_queued_writes_idx = find_metric_idx(metrics, "disk.num_write_jobs");
m_queued_reads_idx = find_metric_idx(metrics, "disk.num_write_jobs");
m_writes_cache_idx = find_metric_idx(metrics, "disk.write_cache_blocks");
m_reads_cache_idx = find_metric_idx(metrics, "disk.read_cache_blocks");
m_pinned_idx = find_metric_idx(metrics, "disk.pinned_blocks");
m_num_blocks_read_idx = find_metric_idx(metrics, "disk.num_blocks_read");
m_cache_hit_idx = find_metric_idx(metrics, "disk.num_blocks_cache_hits");
m_blocks_in_use_idx = find_metric_idx(metrics, "disk.disk_blocks_in_use");
m_blocks_written_idx = find_metric_idx(metrics, "disk.num_blocks_written");
m_write_ops_idx = find_metric_idx(metrics, "disk.num_write_ops");
}
void session_view::set_pos(int pos)
{
m_position = pos;
}
int session_view::pos() const { return m_position; }
int session_view::height() const
{
return 2;
}
void session_view::render()
{
char str[1024];
int pos = 0;
int y = m_position;
float seconds = (m_timestamp[0] - m_timestamp[1]) / 1000000.f;
int download_rate = (m_cnt[0][m_recv_payload_idx] - m_cnt[1][m_recv_payload_idx])
/ seconds;
int upload_rate = (m_cnt[0][m_sent_payload_idx] - m_cnt[1][m_sent_payload_idx])
/ seconds;
pos += snprintf(str, sizeof(str), "| conns: %d down: %s (%s) up: %s (%s)\x1b[K"
, int(m_cnt[0][m_num_peers_idx])
, color(add_suffix(download_rate, "/s"), col_green).c_str()
, color(add_suffix(m_cnt[0][m_recv_payload_idx]), col_green).c_str()
, color(add_suffix(upload_rate, "/s"), col_red).c_str()
, color(add_suffix(m_cnt[0][m_sent_payload_idx]), col_red).c_str());
set_cursor_pos(0, y++);
print(str);
snprintf(str, sizeof(str), "| waste: %s fail: %s unchoked: %d / %d "
"bw queues: %8d (%d) | %8d (%d) disk queues: %d | %d cache: w: %d%% r: %d%% "
"size: w: %s r: %s total: %s\x1b[K"
, add_suffix(m_cnt[0][m_wasted_bytes_idx]).c_str()
, add_suffix(m_cnt[0][m_failed_bytes_idx]).c_str()
, int(m_cnt[0][m_unchoked_idx])
, int(m_cnt[0][m_unchoke_slots_idx])
, int(m_cnt[0][m_limiter_up_bytes_idx])
, int(m_cnt[0][m_limiter_up_queue_idx])
, int(m_cnt[0][m_limiter_down_bytes_idx])
, int(m_cnt[0][m_limiter_down_queue_idx])
, int(m_cnt[0][m_queued_writes_idx])
, int(m_cnt[0][m_queued_reads_idx])
, int((m_cnt[0][m_blocks_written_idx] - m_cnt[0][m_write_ops_idx]) * 100
/ (std::max)(boost::uint64_t(1), m_cnt[0][m_blocks_written_idx]))
, int(m_cnt[0][m_cache_hit_idx] * 100
/ (std::max)(boost::uint64_t(1), m_cnt[0][m_num_blocks_read_idx]))
, add_suffix(m_cnt[0][m_writes_cache_idx] * 16 * 1024).c_str()
, add_suffix(m_cnt[0][m_reads_cache_idx] * 16 * 1024).c_str()
, add_suffix(m_cnt[0][m_blocks_in_use_idx] * 16 * 1024).c_str()
);
set_cursor_pos(0, y++);
print(str);
/*
snprintf(str, sizeof(str), "| timing - "
" read: %6d ms | write: %6d ms | hash: %6d"
, cs.average_read_time / 1000, cs.average_write_time / 1000
, cs.average_hash_time / 1000);
set_cursor_pos(0, y++);
print(str);
snprintf(str, sizeof(str), "| jobs - queued: %4d (%4d) pending: %4d blocked: %4d "
"queued-bytes: %5" PRId64 " kB"
, cs.queued_jobs, cs.peak_queued, cs.pending_jobs, cs.blocked_jobs
, m_cnt[0][m_queued_bytes_idx] / 1000);
set_cursor_pos(0, y++);
print(str);
snprintf(str, sizeof(str), "| cache - total: %4d read: %4d write: %4d pinned: %4d write-queue: %4d"
, cs.read_cache_size + cs.write_cache_size, cs.read_cache_size
, cs.write_cache_size, cs.pinned_blocks
, int(m_cnt[0][m_queued_bytes_idx] / 0x4000));
set_cursor_pos(0, y++);
print(str);
int mru_size = cs.arc_mru_size + cs.arc_mru_ghost_size;
int mfu_size = cs.arc_mfu_size + cs.arc_mfu_ghost_size;
int arc_size = mru_size + mfu_size;
snprintf(str, sizeof(str), "LRU: (%d) %d LFU: %d (%d)\n"
, cs.arc_mru_ghost_size, cs.arc_mru_size
, cs.arc_mfu_size, cs.arc_mfu_ghost_size);
set_cursor_pos(0, y++);
print(str);
str[0] = '\0';
if (arc_size > 0)
{
pos = snprintf(str, sizeof(str), " ");
if (mru_size > 0)
{
pos = snprintf(str + pos, sizeof(str) - pos, "%s"
, progress_bar(cs.arc_mru_ghost_size * 1000 / mru_size
, mru_size * (terminal_width-3) / arc_size, col_yellow, '-', '#').c_str());
}
pos = snprintf(str, sizeof(str), "|");
if (mfu_size)
{
pos = snprintf(str + pos, sizeof(str) - pos, "%s"
, progress_bar(cs.arc_mfu_size * 1000 / mfu_size
, mfu_size * (terminal_width-3) / arc_size, col_green, '=', '-').c_str());
}
}
set_cursor_pos(0, y++);
print(str);
*/
}
void session_view::update_counters(std::vector<boost::uint64_t>& stats_counters
, boost::uint64_t t)
{
// only update the previous counters if there's been enough
// time since it was last updated
if (t - m_timestamp[1] > 2000000)
{
m_cnt[1].swap(m_cnt[0]);
m_timestamp[1] = m_timestamp[0];
}
m_cnt[0].swap(stats_counters);
m_timestamp[0] = t;
render();
}

View File

@ -45,12 +45,17 @@ torrent_view::torrent_view()
: m_active_torrent(0)
, m_scroll_position(0)
, m_torrent_filter(0)
, m_max_lines(30)
, m_width(80)
, m_height(30)
{}
void torrent_view::set_max_size(int height)
void torrent_view::set_size(int width, int height)
{
m_max_lines = height;
if (m_width == width && m_height == height) return;
m_width = width;
m_height = height;
render();
}
int torrent_view::filter() const
@ -136,7 +141,7 @@ void torrent_view::update_torrents(std::vector<lt::torrent_status> const& st)
++i;
continue;
}
if (lines_printed >= m_max_lines)
if (lines_printed >= m_height)
break;
lt::torrent_status const& s = **i;
@ -155,7 +160,7 @@ void torrent_view::update_torrents(std::vector<lt::torrent_status> const& st)
int torrent_view::height() const
{
return int(m_filtered_handles.size() + header_size);
return m_height;
}
void torrent_view::arrow_up()
@ -197,8 +202,8 @@ void torrent_view::render()
// handle scrolling down when moving the cursor
// below the fold
TORRENT_ASSERT(m_scroll_position >= 0);
if (m_active_torrent >= m_max_lines - m_scroll_position)
m_scroll_position = m_active_torrent - m_max_lines + 1;
if (m_active_torrent >= m_height - m_scroll_position)
m_scroll_position = m_active_torrent - m_height+ 1;
TORRENT_ASSERT(m_scroll_position >= 0);
if (m_active_torrent < m_scroll_position)
m_scroll_position = m_active_torrent;
@ -214,7 +219,7 @@ void torrent_view::render()
++i;
continue;
}
if (lines_printed >= m_max_lines)
if (lines_printed >= m_height)
{
print("...\n");
++lines_printed;
@ -234,7 +239,7 @@ void torrent_view::render()
++lines_printed;
}
clear_below(torrent_index + header_size);
clear_rows(torrent_index + header_size, m_height);
}
void torrent_view::print_tabs()
@ -253,6 +258,8 @@ void torrent_view::print_tabs()
}
pos += snprintf(str + pos, sizeof(str) - pos, "\x1b[K");
if (m_width + 1 < sizeof(str))
str[m_width + 1] = '\0';
print(str);
}
@ -269,6 +276,9 @@ void torrent_view::print_headers()
, "#", "Name", "Progress", "Download", "Upload", "Peers (D:S)"
, "Down", "Up", "Flags");
if (m_width + 1 < sizeof(str))
str[m_width + 1] = '\0';
print(str);
}
@ -340,6 +350,9 @@ void torrent_view::print_torrent(lt::torrent_status const& s, bool selected)
}
*/
if (m_width + 1 < sizeof(str))
str[m_width + 1] = '\0';
print(str);
}

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
// TODO: 3 does this need to be exported?
struct TORRENT_EXTRA_EXPORT counters
{
enum stats_counter_t

View File

@ -220,7 +220,7 @@ namespace libtorrent
METRIC(ses, torrent_evicted_counter, type_counter)
// the number of allowed unchoked peers
METRIC(peer, num_unchoke_slots, type_gauge)
METRIC(ses, num_unchoke_slots, type_gauge)
// bittorrent message counters. These counters are incremented
// every time a message of the corresponding type is received from