diff --git a/docs/manual.rst b/docs/manual.rst index 068a651a2..6976d2973 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -2265,7 +2265,7 @@ It contains the following fields:: int active_time; int seeding_time; - float seed_cycles; + int seed_rank; }; ``progress`` is a value in the range [0, 1], that represents the progress of the @@ -2437,10 +2437,9 @@ seconds it has been active while being a seed. ``seeding_time`` should be >= ``active_time`` They are saved in and restored from resume data, to keep totals across sessions. -``seed_cycles`` is the number of times this torrent has reached the seed limits. -It will keep being seeded, but it will rotate between torrents that haven't -completed as many cycles. The fraction part of this number is the progress -of the current cycle. For more information, see queuing_. +``seed_rank`` 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 seed ratio from the tracker scrape. For more information, see queuing_. peer_info @@ -3032,13 +3031,13 @@ counted against the seed limit. is updated, and rotated. ``share_ratio_limit`` is the upload / download ratio limit for considering a -seeding torrent have completed one seed cycle. See queuing_. +seeding torrent have met the seed limit criteria. See queuing_. ``seed_time_ratio_limit`` is the seeding time / downloading time ratio limit -for considering a seeding torrent to have completed one seed cycle. See queuing_. +for considering a seeding torrent to have met the seed limit criteria. See queuing_. ``seed_time_limit`` is the limit on the time a torrent has been an active seed -(specified in seconds) before it is considered having completed one seed cycle. +(specified in seconds) before it is considered having met the seed limit criteria. See queuing_. diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 1877aef3a..b137141e5 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -151,8 +151,7 @@ namespace libtorrent void files_checked(); void start_checking(); - float seed_cycles(session_settings const& s) const; - int seed_cycles_int(session_settings const& s) const { return int(seed_cycles(s)); } + int seed_rank(session_settings const& s) const; storage_mode_t storage_mode() const { return m_storage_mode; } // this will flag the torrent as aborted. The main @@ -876,6 +875,12 @@ namespace libtorrent // stored in resume data size_type m_total_uploaded; size_type m_total_downloaded; + + // if this torrent is running, this was the time + // when it was started. This is used to have a + // bias towards keeping seeding torrents that + // recently was started, to avoid oscillation + ptime m_started; }; inline ptime torrent::next_announce() const diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index d370770bc..db9952735 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -118,7 +118,7 @@ namespace libtorrent , all_time_download(0) , active_time(0) , seeding_time(0) - , seed_cycles(0.f) + , seed_rank(0) {} enum state_t @@ -257,7 +257,8 @@ namespace libtorrent int active_time; int seeding_time; - float seed_cycles; + // higher value means more important to seed + int seed_rank; }; struct TORRENT_EXPORT block_info diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 3e8632825..6cbd4a4c9 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1280,8 +1280,8 @@ namespace aux { , bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2)); std::sort(seeds.begin(), seeds.end() - , bind(&torrent::seed_cycles_int, _1, boost::ref(m_settings)) - < bind(&torrent::seed_cycles_int, _2, boost::ref(m_settings))); + , bind(&torrent::seed_rank, _1, boost::ref(m_settings)) + < bind(&torrent::seed_rank, _2, boost::ref(m_settings))); } for (std::vector::iterator i = downloaders.begin() diff --git a/src/torrent.cpp b/src/torrent.cpp index 444b1d38c..2e49b343b 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -213,6 +213,7 @@ namespace libtorrent , m_seeding_time(seconds(0)) , m_total_uploaded(0) , m_total_downloaded(0) + , m_started(time_now()) { if (resume_data) m_resume_data = *resume_data; #ifndef NDEBUG @@ -286,6 +287,7 @@ namespace libtorrent , m_seeding_time(seconds(0)) , m_total_uploaded(0) , m_total_downloaded(0) + , m_started(time_now()) { if (resume_data) m_resume_data = *resume_data; #ifndef NDEBUG @@ -3285,27 +3287,59 @@ namespace libtorrent m_ses.m_auto_manage_time_scaler = 0; } - float torrent::seed_cycles(session_settings const& s) const + // the higher seed rank, the more important to seed + int torrent::seed_rank(session_settings const& s) const { - if (!is_seed()) return 0.f; + enum flags + { + seed_ratio_not_met = 0x400000, + recently_started = 0x200000, + no_seeds = 0x100000, + prio_mask = 0xfffff + }; - int seeding = total_seconds(m_seeding_time); - int downloading = total_seconds(m_active_time) - seeding; + if (!is_seed()) return 0; - // if the seed time limit is set to less than 60 minutes - // use 60 minutes, to avoid oscillation - float ret = seeding / float((std::max)(s.seed_time_limit, 60 * 60)); + int ret = 0; - // if it took less than 30 minutes to download, disregard the - // seed_time_ratio_limit, since it would make it oscillate too frequent - if (downloading > 30 * 60 && s.seed_time_ratio_limit >= 1.f) - ret = (std::max)(ret, (seeding / downloading - / s.seed_time_ratio_limit)); + ptime now(time_now()); + int seed_time = total_seconds(m_seeding_time); + int download_time = total_seconds(m_active_time) - seed_time; + + // if we haven't yet met the seed limits, set the seed_ratio_not_met + // flag. That will make this seed prioritized size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size()); - if (downloaded > 0 && s.share_ratio_limit >= 1.f) - ret = (std::max)(ret, float(m_total_uploaded) / downloaded - / s.share_ratio_limit); + if (seed_time > s.seed_time_limit + || (seed_time > 1 && download_time / float(seed_time) > s.seed_time_ratio_limit) + || m_total_uploaded / downloaded > s.share_ratio_limit) + ret |= seed_ratio_not_met; + + // if this torrent is running, and it was started less + // than 30 minutes ago, give it priority, to avoid oscillation + if (!is_paused() && now - m_started < minutes(30)) + ret |= recently_started; + + // if we have any scrape data, use it to calculate + // seed rank + int seeds = 0; + int downloaders = 0; + + if (m_complete >= 0) seeds = m_complete; + else seeds = m_policy.num_seeds(); + + if (m_incomplete >= 0) downloaders = m_incomplete; + else downloaders = m_policy.num_peers() - m_policy.num_seeds(); + + if (seeds == 0) + { + ret |= no_seeds; + ret |= downloaders & prio_mask; + } + else + { + ret |= (downloaders * 10 / seeds) & prio_mask; + } return ret; } @@ -3402,6 +3436,7 @@ namespace libtorrent #endif m_paused = false; + m_started = time_now(); // tell the tracker that we're back m_event = tracker_request::started; @@ -3655,7 +3690,7 @@ namespace libtorrent st.list_peers = m_policy.num_peers(); st.list_seeds = m_policy.num_seeds(); st.connect_candidates = m_policy.num_connect_candidates(); - st.seed_cycles = seed_cycles(m_ses.m_settings); + st.seed_rank = seed_rank(m_ses.m_settings); st.all_time_upload = m_total_uploaded; st.all_time_download = m_total_downloaded;