diff --git a/ChangeLog b/ChangeLog index aca1f61a5..5839113c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ 0.15 release + * added torrent priority to affect bandwidth allocation for its peers * reduced the number of floating point operations (to better support systems without FPU) * added new alert when individual files complete diff --git a/bindings/python/src/torrent_handle.cpp b/bindings/python/src/torrent_handle.cpp index 062779206..f694906e6 100644 --- a/bindings/python/src/torrent_handle.cpp +++ b/bindings/python/src/torrent_handle.cpp @@ -313,6 +313,7 @@ void bind_torrent_handle() .def("pause", _(&torrent_handle::pause)) .def("resume", _(&torrent_handle::resume)) .def("clear_error", _(&torrent_handle::clear_error)) + .def("set_priority", _(&torrent_handle::set_priority)) .def("is_auto_managed", _(&torrent_handle::is_auto_managed)) .def("auto_managed", _(&torrent_handle::auto_managed)) diff --git a/bindings/python/src/torrent_status.cpp b/bindings/python/src/torrent_status.cpp index ae53fd85f..1f83af9be 100644 --- a/bindings/python/src/torrent_status.cpp +++ b/bindings/python/src/torrent_status.cpp @@ -78,6 +78,7 @@ void bind_torrent_status() .def_readonly("seed_rank", &torrent_status::seed_rank) .def_readonly("last_scrape", &torrent_status::last_scrape) .def_readonly("error", &torrent_status::error) + .def_readonly("priority", &torrent_status::priority) ; enum_("states") diff --git a/docs/manual.rst b/docs/manual.rst index 2dbebede5..32a810b9f 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -1893,6 +1893,8 @@ Its declaration looks like this:: void queue_position_top() const; void queue_position_bottom() const; + void set_priority(int prio) const; + void use_interface(char const* net_interface) const; void pause() const; @@ -2508,6 +2510,25 @@ The ``queue_position_*()`` functions adjust the torrents position in the queue. closer to the front and down means closer to the back of the queue. Top and bottom refers to the front and the back of the queue respectively. +set_priority() +-------------- + + :: + + void set_priority(int prio) const; + +This sets the bandwidth priority of this torrent. The priority of a torrent determines +how much bandwidth its peers are assigned when distributing upload and download rate quotas. +A high number gives more bandwidth. The priority must be within the range [0, 255]. + +The default priority is, which is the lowest priority. + +To query the priority of a torrent, use the `status()`_ call. + +Torrents with higher priority will not nececcarily get as much bandwidth as they can +consume, even if there's is more quota. Other peers will still be weighed in when +bandwidth is being distributed. With other words, bandwidth is not distributed strictly +in order of priority, but the priority is used as a weight. use_interface() --------------- @@ -2869,6 +2890,8 @@ It contains the following fields:: bool seed_mode; bool upload_mode; + + int priority; }; ``progress`` is a value in the range [0, 1], that represents the progress of the diff --git a/include/libtorrent/bandwidth_queue_entry.hpp b/include/libtorrent/bandwidth_queue_entry.hpp index e3dfbe467..ac6d89322 100644 --- a/include/libtorrent/bandwidth_queue_entry.hpp +++ b/include/libtorrent/bandwidth_queue_entry.hpp @@ -77,7 +77,8 @@ struct bw_request for (int j = 0; j < 5 && channel[j]; ++j) { if (channel[j]->throttle() == 0) continue; - quota = (std::min)(channel[j]->distribute_quota * priority / channel[j]->tmp, quota); + quota = (std::min)(int(boost::uint64_t(channel[j]->distribute_quota) + * priority / channel[j]->tmp), quota); } assigned += quota; for (int j = 0; j < 5 && channel[j]; ++j) diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 70ca422f0..d85b66491 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -228,6 +228,8 @@ namespace libtorrent void set_priority(int p) { TORRENT_ASSERT(p > 0); + TORRENT_ASSERT(m_priority <= 255); + if (p > 255) p = 255; m_priority = p; } diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 451367dfa..e56adcbad 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -286,6 +286,15 @@ namespace libtorrent float ratio() const { return m_ratio; } + int priority() const { return m_priority; } + void set_priority(int prio) + { + TORRENT_ASSERT(prio <= 255 && prio >= 0); + if (prio > 255) prio = 255; + else if (prio < 0) prio = 0; + m_priority = prio; + } + #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES void resolve_countries(bool r) { m_resolve_countries = r; } @@ -1015,6 +1024,11 @@ namespace libtorrent // is called and the time scaler is reset to 10. boost::int8_t m_time_scaler; + // this is the priority of the torrent. The higher + // the value is, the more bandwidth is assigned to + // the torrent's peers + boost::uint8_t m_priority; + // is set to true when the torrent has // been aborted. bool m_abort:1; diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 98e2722af..33a0e17f6 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -118,6 +118,8 @@ namespace libtorrent , has_incoming(false) , sparse_regions(0) , seed_mode(false) + , upload_mode(false) + , priority(0) {} enum state_t @@ -293,6 +295,9 @@ namespace libtorrent // from downloading, typically caused by a file // write operation failing bool upload_mode; + + // the priority of this torrent + int priority; }; struct TORRENT_EXPORT block_info @@ -384,6 +389,8 @@ namespace libtorrent enum deadline_flags { alert_when_available = 1 }; void set_piece_deadline(int index, time_duration deadline, int flags = 0) const; + + void set_priority(int prio) const; #ifndef TORRENT_NO_DEPRECATE #if !TORRENT_NO_FPU diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 1c73e83ee..d5050d127 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -3877,6 +3877,10 @@ namespace libtorrent { shared_ptr t = m_torrent.lock(); int priority = 1 + is_interesting() * 2 + m_requests_in_buffer.size(); + + if (priority > 255) priority = 255; + priority += t->priority() << 8; + // peers that we are not interested in are non-prioritized m_channel_state[upload_channel] = peer_info::bw_limit; m_ses.m_upload_rate.request_bandwidth(self() @@ -3905,12 +3909,15 @@ namespace libtorrent "download: " << (m_download_queue.size() * 16 * 1024 + 30) << " prio: " << m_priority << " ]\n"; #endif + TORRENT_ASSERT(m_priority <= 255); + int priority = m_priority + (t->priority() << 8); + TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle || m_channel_state[download_channel] == peer_info::bw_disk); TORRENT_ASSERT(m_outstanding_bytes >= 0); m_channel_state[download_channel] = peer_info::bw_limit; m_ses.m_download_rate.request_bandwidth(self() - , m_outstanding_bytes + 30, m_priority + , m_outstanding_bytes + 30, priority , bwc1, bwc2, bwc3, bwc4); } diff --git a/src/torrent.cpp b/src/torrent.cpp index 4158b631e..de43c7eb7 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -5761,6 +5761,7 @@ namespace libtorrent st.upload_mode = m_upload_mode; st.up_bandwidth_queue = 0; st.down_bandwidth_queue = 0; + st.priority = m_priority; st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() , !boost::bind(&peer_connection::is_connecting, _1)); diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 568e845e3..378cb1f68 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -326,6 +326,12 @@ namespace libtorrent TORRENT_FORWARD(auto_managed(m)); } + void torrent_handle::set_priority(int p) const + { + INVARIANT_CHECK; + TORRENT_FORWARD(set_priority(p)); + } + int torrent_handle::queue_position() const { INVARIANT_CHECK;