automatically scrape auto managed torrents to keep track of downloader/seed ratio

This commit is contained in:
Arvid Norberg 2008-05-19 04:06:25 +00:00
parent c460704a5f
commit 777954ab3e
9 changed files with 113 additions and 6 deletions

View File

@ -2265,6 +2265,8 @@ struct torrent_status
int seeding_time; int seeding_time;
int seed_rank; int seed_rank;
int last_scrape;
}; };
</pre> </pre>
<p><tt class="docutils literal"><span class="pre">progress</span></tt> is a value in the range [0, 1], that represents the progress of the <p><tt class="docutils literal"><span class="pre">progress</span></tt> is a value in the range [0, 1], that represents the progress of the
@ -2421,6 +2423,8 @@ across sessions.</p>
<p><tt class="docutils literal"><span class="pre">seed_rank</span></tt> is a rank of how important it is to seed the torrent, it is used <p><tt class="docutils literal"><span class="pre">seed_rank</span></tt> is a rank of how important it is to seed the torrent, it is used
to determine which torrents to seed and which to queue. It is based on the peer to determine which torrents to seed and which to queue. It is based on the peer
to seed ratio from the tracker scrape. For more information, see <a class="reference internal" href="#queuing">queuing</a>.</p> to seed ratio from the tracker scrape. For more information, see <a class="reference internal" href="#queuing">queuing</a>.</p>
<p><tt class="docutils literal"><span class="pre">last_scrape</span></tt> is the number of seconds since this torrent acquired scrape data.
If it has never done that, this value is -1.</p>
</div> </div>
<div class="section" id="peer-info"> <div class="section" id="peer-info">
<h1>peer_info</h1> <h1>peer_info</h1>
@ -2801,6 +2805,9 @@ struct session_settings
float seed_time_ratio_limit; float seed_time_ratio_limit;
int seed_time_limit; int seed_time_limit;
bool close_redundant_connections; bool close_redundant_connections;
int auto_scrape_interval;
int auto_scrape_min_interval;
}; };
</pre> </pre>
<p><tt class="docutils literal"><span class="pre">user_agent</span></tt> this is the client identification to the tracker. <p><tt class="docutils literal"><span class="pre">user_agent</span></tt> this is the client identification to the tracker.
@ -2978,6 +2985,15 @@ See <a class="reference internal" href="#queuing">queuing</a>.</p>
connections where both ends have no utility in keeping the connection open. connections where both ends have no utility in keeping the connection open.
For instance if both ends have completed their downloads, there's no point For instance if both ends have completed their downloads, there's no point
in keeping it open. This defaults to <tt class="docutils literal"><span class="pre">true</span></tt>.</p> in keeping it open. This defaults to <tt class="docutils literal"><span class="pre">true</span></tt>.</p>
<p><tt class="docutils literal"><span class="pre">auto_scrape_interval</span></tt> is the number of seconds between scrapes of
queued torrents (auto managed and paused torrents). Auto managed
torrents that are paused, are scraped regularly in order to keep
track of their downloader/seed ratio. This ratio is used to determine
which torrents to seed and which to pause.</p>
<p><tt class="docutils literal"><span class="pre">auto_scrape_min_interval</span></tt> is the minimum number of seconds between any
automatic scrape (regardless of torrent). In case there are a large number
of paused auto managed torrents, this puts a limit on how often a scrape
request is sent.</p>
</div> </div>
<div class="section" id="pe-settings"> <div class="section" id="pe-settings">
<h1>pe_settings</h1> <h1>pe_settings</h1>

View File

@ -2229,6 +2229,8 @@ It contains the following fields::
int seeding_time; int seeding_time;
int seed_rank; int seed_rank;
int last_scrape;
}; };
``progress`` is a value in the range [0, 1], that represents the progress of the ``progress`` is a value in the range [0, 1], that represents the progress of the
@ -2404,6 +2406,9 @@ across sessions.
to determine which torrents to seed and which to queue. It is based on the peer to determine which torrents to seed and which to queue. It is based on the peer
to seed ratio from the tracker scrape. For more information, see queuing_. to seed ratio from the tracker scrape. For more information, see queuing_.
``last_scrape`` is the number of seconds since this torrent acquired scrape data.
If it has never done that, this value is -1.
peer_info peer_info
========= =========
@ -2784,6 +2789,9 @@ that will be sent to the tracker. The user-agent is a good way to identify your
float seed_time_ratio_limit; float seed_time_ratio_limit;
int seed_time_limit; int seed_time_limit;
bool close_redundant_connections; bool close_redundant_connections;
int auto_scrape_interval;
int auto_scrape_min_interval;
}; };
``user_agent`` this is the client identification to the tracker. ``user_agent`` this is the client identification to the tracker.
@ -3009,6 +3017,17 @@ connections where both ends have no utility in keeping the connection open.
For instance if both ends have completed their downloads, there's no point For instance if both ends have completed their downloads, there's no point
in keeping it open. This defaults to ``true``. in keeping it open. This defaults to ``true``.
``auto_scrape_interval`` is the number of seconds between scrapes of
queued torrents (auto managed and paused torrents). Auto managed
torrents that are paused, are scraped regularly in order to keep
track of their downloader/seed ratio. This ratio is used to determine
which torrents to seed and which to pause.
``auto_scrape_min_interval`` is the minimum number of seconds between any
automatic scrape (regardless of torrent). In case there are a large number
of paused auto managed torrents, this puts a limit on how often a scrape
request is sent.
pe_settings pe_settings
=========== ===========

View File

@ -1278,8 +1278,9 @@ int main(int ac, char* av[])
<< "swarm: " << to_string(downloaders, 4) << ":" << to_string(seeds, 4) << "swarm: " << to_string(downloaders, 4) << ":" << to_string(seeds, 4)
<< " bw queue: (" << s.up_bandwidth_queue << " | " << s.down_bandwidth_queue << ") " << " bw queue: (" << s.up_bandwidth_queue << " | " << s.down_bandwidth_queue << ") "
"all-time (Rx: " << esc("32") << add_suffix(s.all_time_download) << term "all-time (Rx: " << esc("32") << add_suffix(s.all_time_download) << term
<< " Tx: " << esc("31") << add_suffix(s.all_time_upload) << term << ") " << std::hex << s.seed_rank << std::dec << "\n" << " Tx: " << esc("31") << add_suffix(s.all_time_upload) << term << ") "
<< esc("0"); << std::hex << s.seed_rank << std::dec << " "
<< s.last_scrape << "\n" << esc("0");
if (s.state != torrent_status::seeding) if (s.state != torrent_status::seeding)
{ {

View File

@ -489,6 +489,11 @@ namespace libtorrent
// from the torrent with the most peers // from the torrent with the most peers
int m_disconnect_time_scaler; int m_disconnect_time_scaler;
// when this scaler reaches zero, it will
// scrape one of the auto managed, paused,
// torrents.
int m_auto_scrape_time_scaler;
// statistics gathered from all torrents. // statistics gathered from all torrents.
stat m_stat; stat m_stat;

View File

@ -133,6 +133,8 @@ namespace libtorrent
, peer_turnover(1 / 50.f) , peer_turnover(1 / 50.f)
, peer_turnover_cutoff(1.f) , peer_turnover_cutoff(1.f)
, close_redundant_connections(true) , close_redundant_connections(true)
, auto_scrape_interval(1800)
, auto_scrape_min_interval(300)
{} {}
// this is the user agent that will be sent to the tracker // this is the user agent that will be sent to the tracker
@ -392,6 +394,14 @@ namespace libtorrent
// are closed. for instance if both ends have completed // are closed. for instance if both ends have completed
// their downloads // their downloads
bool close_redundant_connections; bool close_redundant_connections;
// the number of seconds between scrapes of
// queued torrents (auto managed and paused)
int auto_scrape_interval;
// the minimum number of seconds between any
// automatic scrape (regardless of torrent)
int auto_scrape_min_interval;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT

View File

@ -355,6 +355,7 @@ namespace libtorrent
void force_tracker_request(); void force_tracker_request();
void force_tracker_request(ptime); void force_tracker_request(ptime);
void scrape_tracker(); void scrape_tracker();
ptime const& last_scrape() const { return m_last_scrape; }
// sets the username and password that will be sent to // sets the username and password that will be sent to
// the tracker // the tracker
@ -614,6 +615,10 @@ namespace libtorrent
// recently was started, to avoid oscillation // recently was started, to avoid oscillation
ptime m_started; ptime m_started;
// the last time we initiated a scrape request to
// one of the trackers in this torrent
ptime m_last_scrape;
boost::intrusive_ptr<torrent_info> m_torrent_file; boost::intrusive_ptr<torrent_info> m_torrent_file;
tracker_request::event_t m_event; tracker_request::event_t m_event;

View File

@ -119,6 +119,7 @@ namespace libtorrent
, active_time(0) , active_time(0)
, seeding_time(0) , seeding_time(0)
, seed_rank(0) , seed_rank(0)
, last_scrape(0)
{} {}
enum state_t enum state_t
@ -259,6 +260,10 @@ namespace libtorrent
// higher value means more important to seed // higher value means more important to seed
int seed_rank; int seed_rank;
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
}; };
struct TORRENT_EXPORT block_info struct TORRENT_EXPORT block_info

View File

@ -166,6 +166,7 @@ namespace aux {
, m_auto_manage_time_scaler(0) , m_auto_manage_time_scaler(0)
, m_optimistic_unchoke_time_scaler(0) , m_optimistic_unchoke_time_scaler(0)
, m_disconnect_time_scaler(90) , m_disconnect_time_scaler(90)
, m_auto_scrape_time_scaler(180)
, m_incoming_connection(false) , m_incoming_connection(false)
, m_last_tick(time_now()) , m_last_tick(time_now())
, m_torrent_sequence(0) , m_torrent_sequence(0)
@ -1012,7 +1013,6 @@ namespace aux {
<< m_disk_thread.disk_allocations() << "\t" << m_disk_thread.disk_allocations() << "\t"
<< std::endl; << std::endl;
#endif #endif
// -------------------------------------------------------------- // --------------------------------------------------------------
// second_tick every torrent // second_tick every torrent
// -------------------------------------------------------------- // --------------------------------------------------------------
@ -1028,6 +1028,9 @@ namespace aux {
// count the number of peers of downloading torrents // count the number of peers of downloading torrents
int num_downloads_peers = 0; int num_downloads_peers = 0;
torrent_map::iterator least_recently_scraped = m_torrents.begin();
int num_paused_auto_managed = 0;
// check each torrent for tracker updates // check each torrent for tracker updates
// TODO: do this in a timer-event in each torrent instead // TODO: do this in a timer-event in each torrent instead
for (torrent_map::iterator i = m_torrents.begin(); for (torrent_map::iterator i = m_torrents.begin();
@ -1040,6 +1043,17 @@ namespace aux {
else else
++uncongested_torrents; ++uncongested_torrents;
if (t.is_auto_managed() && t.is_paused())
{
++num_paused_auto_managed;
if (!least_recently_scraped->second->is_auto_managed()
|| !least_recently_scraped->second->is_paused()
|| least_recently_scraped->second->last_scrape() > t.last_scrape())
{
least_recently_scraped = i;
}
}
if (t.is_finished()) if (t.is_finished())
{ {
++num_seeds; ++num_seeds;
@ -1078,6 +1092,22 @@ namespace aux {
m_stat.second_tick(tick_interval); m_stat.second_tick(tick_interval);
// --------------------------------------------------------------
// scrape paused torrents that are auto managed
// --------------------------------------------------------------
--m_auto_scrape_time_scaler;
if (m_auto_scrape_time_scaler <= 0)
{
m_auto_scrape_time_scaler = m_settings.auto_scrape_interval
/ (std::max)(1, num_paused_auto_managed);
if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval)
m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval;
if (least_recently_scraped != m_torrents.end())
{
least_recently_scraped->second->scrape_tracker();
}
}
// -------------------------------------------------------------- // --------------------------------------------------------------
// connect new peers // connect new peers
@ -1189,7 +1219,7 @@ namespace aux {
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*c.m_logger) << "*** CONNECTION TIMED OUT\n"; (*c.m_logger) << "*** CONNECTION TIMED OUT\n";
#endif #endif
c.disconnect("timed out: inactive", true); c.disconnect("timed out: inactive", 1);
continue; continue;
} }

View File

@ -153,6 +153,7 @@ namespace libtorrent
, m_total_uploaded(0) , m_total_uploaded(0)
, m_total_downloaded(0) , m_total_downloaded(0)
, m_started(time_now()) , m_started(time_now())
, m_last_scrape(min_time())
, m_torrent_file(tf) , m_torrent_file(tf)
, m_event(tracker_request::started) , m_event(tracker_request::started)
, m_storage(0) , m_storage(0)
@ -227,6 +228,7 @@ namespace libtorrent
, m_total_uploaded(0) , m_total_uploaded(0)
, m_total_downloaded(0) , m_total_downloaded(0)
, m_started(time_now()) , m_started(time_now())
, m_last_scrape(min_time())
, m_torrent_file(new torrent_info(info_hash)) , m_torrent_file(new torrent_info(info_hash))
, m_event(tracker_request::started) , m_event(tracker_request::started)
, m_storage(0) , m_storage(0)
@ -754,6 +756,8 @@ namespace libtorrent
req.url = m_trackers[m_currently_trying_tracker].url; req.url = m_trackers[m_currently_trying_tracker].url;
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this()); , tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
m_last_scrape = time_now();
} }
// returns true if it is time for this torrent to make another // returns true if it is time for this torrent to make another
@ -832,6 +836,8 @@ namespace libtorrent
if (complete >= 0) m_complete = complete; if (complete >= 0) m_complete = complete;
if (incomplete >= 0) m_incomplete = incomplete; if (incomplete >= 0) m_incomplete = incomplete;
if (complete >= 0 && incomplete >= 0)
m_last_scrape = time_now();
// connect to random peers from the list // connect to random peers from the list
std::random_shuffle(peer_list.begin(), peer_list.end()); std::random_shuffle(peer_list.begin(), peer_list.end());
@ -3788,8 +3794,18 @@ namespace libtorrent
, m_have_pieces.end() , m_have_pieces.end()
, 0) == m_num_pieces); , 0) == m_num_pieces);
ptime now = time_now();
torrent_status st; torrent_status st;
if (m_last_scrape == min_time())
{
st.last_scrape = -1;
}
else
{
st.last_scrape = total_seconds(now - m_last_scrape);
}
st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size(); st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size(); st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
@ -3837,7 +3853,7 @@ namespace libtorrent
st.upload_payload_rate = m_stat.upload_payload_rate(); st.upload_payload_rate = m_stat.upload_payload_rate();
st.next_announce = boost::posix_time::seconds( st.next_announce = boost::posix_time::seconds(
total_seconds(next_announce() - time_now())); total_seconds(next_announce() - now));
if (st.next_announce.is_negative()) if (st.next_announce.is_negative())
st.next_announce = boost::posix_time::seconds(0); st.next_announce = boost::posix_time::seconds(0);