completed queuing. It is now possible to change and query queue position of torrents.
This commit is contained in:
parent
63cf889be4
commit
31c9d378f5
|
@ -197,7 +197,7 @@ struct peer_plugin
|
|||
virtual bool on_interested();
|
||||
virtual bool on_not_interested();
|
||||
virtual bool on_have(int index);
|
||||
virtual bool on_bitfield(std::vector<bool> const& bitfield);
|
||||
virtual bool on_bitfield(bitfield const& bits);
|
||||
virtual bool on_have_all();
|
||||
virtual bool on_have_none();
|
||||
virtual bool on_allowed_fast(int index);
|
||||
|
|
1279
docs/manual.html
1279
docs/manual.html
File diff suppressed because it is too large
Load Diff
|
@ -1520,6 +1520,12 @@ Its declaration looks like this::
|
|||
void set_peer_upload_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
||||
void set_peer_download_limit(asio::ip::tcp::endpoint ip, int limit) const;
|
||||
|
||||
int queue_position() const;
|
||||
void queue_position_up() const;
|
||||
void queue_position_down() const;
|
||||
void queue_position_top() const;
|
||||
void queue_position_bottom() const;
|
||||
|
||||
void use_interface(char const* net_interface) const;
|
||||
|
||||
void pause() const;
|
||||
|
@ -1878,6 +1884,33 @@ automatically from the list.
|
|||
See `HTTP seeding`_ for more information.
|
||||
|
||||
|
||||
queue_position() queue_position_up() queue_position_down() queue_position_top() queue_position_bottom()
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
int queue_position() const;
|
||||
void queue_position_up() const;
|
||||
void queue_position_down() const;
|
||||
void queue_position_top() const;
|
||||
void queue_position_bottom() const;
|
||||
|
||||
Every torrent that is added is assigned a queue position exactly one greater than
|
||||
the greatest queue position of all existing torrents. Torrents that are being
|
||||
seeded have -1 as their queue position, since they're no longer in line to be downloaded.
|
||||
|
||||
When a torrent is removed or turns into a seed, all torrents with greater queue positions
|
||||
have their positions decreased to fill in the space in the sequence.
|
||||
|
||||
``queue_position()`` returns the torrent's position in the download queue. The torrents
|
||||
with the smallest numbers are the ones that are being downloaded. The smaller number,
|
||||
the closer the torrent is to the front of the line to be started.
|
||||
|
||||
The ``queue_position_*()`` functions adjust the torrents position in the queue. Up means
|
||||
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.
|
||||
|
||||
|
||||
use_interface()
|
||||
---------------
|
||||
|
||||
|
@ -4471,7 +4504,20 @@ See `save_resume_data()`_.
|
|||
downloading
|
||||
-----------
|
||||
|
||||
**TODO: finish**
|
||||
Torrents that are currently being downloaded or incomplete (with bytes still to download)
|
||||
are queued. The torrents in the front of the queue are started to be actively downloaded
|
||||
and the rest are ordered with regards to their queue position. Any newly added torrent
|
||||
is placed at the end of the queue. Once a torrent is removed or turns into a seed, its
|
||||
queue position is -1 and all torrents that used to be after it in the queue, decreases their
|
||||
position in order to fill the gap.
|
||||
|
||||
The queue positions are always in a sequence without any gaps.
|
||||
|
||||
Lower queue position means closer to the front of the queue, and will be started sooner than
|
||||
torrents with higher queue positions.
|
||||
|
||||
To query a torrent for its position in the queue, or change its position, see:
|
||||
`queue_position() queue_position_up() queue_position_down() queue_position_top() queue_position_bottom()`_.
|
||||
|
||||
seeding
|
||||
-------
|
||||
|
|
|
@ -573,6 +573,7 @@ void scan_dir(path const& dir_path
|
|||
continue;
|
||||
}
|
||||
|
||||
h.auto_managed(false);
|
||||
h.pause();
|
||||
// the alert handler for save_resume_data_alert
|
||||
// will save it to disk and remove the torrent
|
||||
|
@ -1180,7 +1181,7 @@ int main(int ac, char* av[])
|
|||
boost::filesystem::ofstream out(h.save_path() / (h.name() + ".fastresume"), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), *p->resume_data);
|
||||
if (h.is_paused()) ses.remove_torrent(h);
|
||||
if (h.is_paused() && !h.is_auto_managed()) ses.remove_torrent(h);
|
||||
}
|
||||
}
|
||||
else if (torrent_alert* p = dynamic_cast<torrent_alert*>(a.get()))
|
||||
|
@ -1232,13 +1233,17 @@ int main(int ac, char* av[])
|
|||
if (active_torrent == torrent_index)
|
||||
{
|
||||
term = "\x1b[0m\x1b[7m";
|
||||
out << esc("7") << "* ";
|
||||
out << esc("7") << "*";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "- ";
|
||||
out << " ";
|
||||
}
|
||||
|
||||
int queue_pos = h.queue_position();
|
||||
if (queue_pos == -1) out << "- ";
|
||||
else out << std::setw(3) << queue_pos;
|
||||
|
||||
if (h.is_paused()) out << esc("34");
|
||||
else out << esc("37");
|
||||
out << std::setw(40) << std::setiosflags(std::ios::left);
|
||||
|
|
|
@ -514,10 +514,6 @@ namespace libtorrent
|
|||
// port we'll bind the next outgoing socket to
|
||||
int m_next_port;
|
||||
|
||||
// the sequence number to assign to the
|
||||
// next torrent that's added
|
||||
int m_torrent_sequence;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
boost::intrusive_ptr<dht::dht_tracker> m_dht;
|
||||
dht_settings m_dht_settings;
|
||||
|
|
|
@ -169,6 +169,9 @@ namespace libtorrent
|
|||
|
||||
void set_sequential_download(bool sd);
|
||||
|
||||
void set_queue_position(int p);
|
||||
int queue_position() const { return m_sequence_number; }
|
||||
|
||||
void second_tick(stat& accumulator, float tick_interval);
|
||||
|
||||
// debug purpose only
|
||||
|
|
|
@ -346,6 +346,12 @@ namespace libtorrent
|
|||
bool is_auto_managed() const;
|
||||
void auto_managed(bool m) const;
|
||||
|
||||
int queue_position() const;
|
||||
void queue_position_up() const;
|
||||
void queue_position_down() const;
|
||||
void queue_position_top() const;
|
||||
void queue_position_bottom() const;
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
void resolve_countries(bool r);
|
||||
bool resolve_countries() const;
|
||||
|
|
|
@ -169,7 +169,6 @@ namespace aux {
|
|||
, m_auto_scrape_time_scaler(180)
|
||||
, m_incoming_connection(false)
|
||||
, m_last_tick(time_now())
|
||||
, m_torrent_sequence(0)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, m_dht_same_port(true)
|
||||
, m_external_udp_port(0)
|
||||
|
@ -1703,6 +1702,14 @@ namespace aux {
|
|||
#endif
|
||||
}
|
||||
|
||||
int queue_pos = 0;
|
||||
for (torrent_map::const_iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
{
|
||||
int pos = i->second->queue_position();
|
||||
if (pos >= queue_pos) queue_pos = pos + 1;
|
||||
}
|
||||
|
||||
// create the torrent and the data associated with
|
||||
// the checker thread and store it before starting
|
||||
// the thread
|
||||
|
@ -1711,17 +1718,16 @@ namespace aux {
|
|||
torrent_ptr.reset(new torrent(*this, params.ti, params.save_path
|
||||
, m_listen_interface, params.storage_mode, 16 * 1024
|
||||
, params.storage, params.paused, params.resume_data
|
||||
, m_torrent_sequence, params.auto_managed));
|
||||
, queue_pos, params.auto_managed));
|
||||
}
|
||||
else
|
||||
{
|
||||
torrent_ptr.reset(new torrent(*this, params.tracker_url, *ih, params.name
|
||||
, params.save_path, m_listen_interface, params.storage_mode, 16 * 1024
|
||||
, params.storage, params.paused, params.resume_data
|
||||
, m_torrent_sequence, params.auto_managed));
|
||||
, queue_pos, params.auto_managed));
|
||||
}
|
||||
torrent_ptr->start();
|
||||
++m_torrent_sequence;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
|
@ -1745,6 +1751,11 @@ namespace aux {
|
|||
|
||||
m_torrents.insert(std::make_pair(*ih, torrent_ptr));
|
||||
|
||||
// if this is an auto managed torrent, force a recalculation
|
||||
// of which torrents to have active
|
||||
if (params.auto_managed && m_auto_manage_time_scaler > 2)
|
||||
m_auto_manage_time_scaler = 2;
|
||||
|
||||
return torrent_handle(torrent_ptr);
|
||||
}
|
||||
|
||||
|
@ -1816,6 +1827,7 @@ namespace aux {
|
|||
#ifndef NDEBUG
|
||||
sha1_hash i_hash = t.torrent_file().info_hash();
|
||||
#endif
|
||||
i->second->set_queue_position(-1);
|
||||
m_torrents.erase(i);
|
||||
TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
|
||||
return;
|
||||
|
@ -2440,6 +2452,22 @@ namespace aux {
|
|||
#ifndef NDEBUG
|
||||
void session_impl::check_invariant() const
|
||||
{
|
||||
std::set<int> unique;
|
||||
int total_downloaders = 0;
|
||||
for (torrent_map::const_iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
{
|
||||
int pos = i->second->queue_position();
|
||||
if (pos < 0)
|
||||
{
|
||||
TORRENT_ASSERT(pos == -1);
|
||||
continue;
|
||||
}
|
||||
++total_downloaders;
|
||||
unique.insert(i->second->queue_position());
|
||||
}
|
||||
TORRENT_ASSERT(unique.size() == total_downloaders);
|
||||
|
||||
TORRENT_ASSERT(m_max_connections > 0);
|
||||
TORRENT_ASSERT(m_max_uploads > 0);
|
||||
TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads);
|
||||
|
|
|
@ -1195,7 +1195,6 @@ namespace libtorrent
|
|||
?"disk failed":"failed") << " ]\n";
|
||||
#endif
|
||||
|
||||
bool was_seed = is_seed();
|
||||
bool was_finished = m_picker->num_filtered() + num_pieces()
|
||||
== torrent_file().num_pieces();
|
||||
|
||||
|
@ -1212,17 +1211,6 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(valid_metadata());
|
||||
// if we just became a seed, picker is now invalid, since it
|
||||
// is deallocated by the torrent once it starts seeding
|
||||
if (!was_finished
|
||||
&& (is_seed()
|
||||
|| m_picker->num_filtered() + num_pieces()
|
||||
== torrent_file().num_pieces()))
|
||||
{
|
||||
// torrent finished
|
||||
// i.e. all the pieces we're interested in have
|
||||
// been downloaded. Release the files (they will open
|
||||
// in read only mode if needed)
|
||||
finished();
|
||||
}
|
||||
}
|
||||
else if (passed_hash_check == -2)
|
||||
{
|
||||
|
@ -1236,10 +1224,17 @@ namespace libtorrent
|
|||
|
||||
m_policy.piece_finished(index, passed_hash_check == 0);
|
||||
|
||||
if (!was_seed && is_seed())
|
||||
if (!was_finished
|
||||
&& (is_seed()
|
||||
|| m_picker->num_filtered() + num_pieces()
|
||||
== torrent_file().num_pieces()))
|
||||
{
|
||||
TORRENT_ASSERT(passed_hash_check == 0);
|
||||
completed();
|
||||
// torrent finished
|
||||
// i.e. all the pieces we're interested in have
|
||||
// been downloaded. Release the files (they will open
|
||||
// in read only mode if needed)
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1527,11 +1522,6 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
if (is_seed())
|
||||
{
|
||||
m_state = torrent_status::seeding;
|
||||
m_picker.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::string torrent::tracker_login() const
|
||||
|
@ -2996,6 +2986,12 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
m_state = torrent_status::finished;
|
||||
set_queue_position(-1);
|
||||
|
||||
// we have to call completed() before we start
|
||||
// disconnecting peers, since there's an assert
|
||||
// to make sure we're cleared the piece picker
|
||||
if (is_seed()) completed();
|
||||
|
||||
// disconnect all seeds
|
||||
// TODO: should disconnect all peers that have the pieces we have
|
||||
|
@ -3030,6 +3026,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
m_state = torrent_status::downloading;
|
||||
set_queue_position((std::numeric_limits<int>::max)());
|
||||
}
|
||||
|
||||
// called when torrent is complete (all pieces downloaded)
|
||||
|
@ -3037,6 +3034,8 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_picker.reset();
|
||||
|
||||
// make the next tracker request
|
||||
// be a completed-event
|
||||
m_event = tracker_request::completed;
|
||||
|
@ -3135,11 +3134,7 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_seed())
|
||||
{
|
||||
m_state = torrent_status::seeding;
|
||||
m_picker.reset();
|
||||
}
|
||||
if (is_seed()) finished();
|
||||
|
||||
if (!m_connections_initialized)
|
||||
{
|
||||
|
@ -3369,6 +3364,55 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void torrent::set_queue_position(int p)
|
||||
{
|
||||
if (p == m_sequence_number) return;
|
||||
|
||||
session_impl::torrent_map& torrents = m_ses.m_torrents;
|
||||
if (p < 0)
|
||||
{
|
||||
for (session_impl::torrent_map::iterator i = torrents.begin()
|
||||
, end(torrents.end()); i != end; ++i)
|
||||
{
|
||||
torrent* t = i->second.get();
|
||||
if (t == this) continue;
|
||||
if (t->m_sequence_number >= m_sequence_number
|
||||
&& t->m_sequence_number != -1)
|
||||
--t->m_sequence_number;
|
||||
}
|
||||
m_sequence_number = p;
|
||||
}
|
||||
else if (p < m_sequence_number)
|
||||
{
|
||||
for (session_impl::torrent_map::iterator i = torrents.begin()
|
||||
, end(torrents.end()); i != end; ++i)
|
||||
{
|
||||
torrent* t = i->second.get();
|
||||
if (t == this) continue;
|
||||
if (t->m_sequence_number >= p
|
||||
&& t->m_sequence_number != -1)
|
||||
++t->m_sequence_number;
|
||||
}
|
||||
m_sequence_number = p;
|
||||
}
|
||||
else if (p > m_sequence_number)
|
||||
{
|
||||
int max_seq = 0;
|
||||
for (session_impl::torrent_map::iterator i = torrents.begin()
|
||||
, end(torrents.end()); i != end; ++i)
|
||||
{
|
||||
torrent* t = i->second.get();
|
||||
if (t == this) continue;
|
||||
int pos = t->m_sequence_number;
|
||||
if (pos <= p
|
||||
&& pos > m_sequence_number
|
||||
&& pos != -1)
|
||||
--t->m_sequence_number;
|
||||
if (pos > max_seq) max_seq = pos;
|
||||
}
|
||||
m_sequence_number = (std::min)(max_seq + 1, p);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::set_max_uploads(int limit)
|
||||
{
|
||||
|
|
|
@ -283,6 +283,36 @@ namespace libtorrent
|
|||
TORRENT_FORWARD(auto_managed(m));
|
||||
}
|
||||
|
||||
int torrent_handle::queue_position() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD_RETURN(queue_position(), -1);
|
||||
}
|
||||
|
||||
void torrent_handle::queue_position_up() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(set_queue_position(t->queue_position() - 1));
|
||||
}
|
||||
|
||||
void torrent_handle::queue_position_down() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(set_queue_position(t->queue_position() + 1));
|
||||
}
|
||||
|
||||
void torrent_handle::queue_position_top() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(set_queue_position(0));
|
||||
}
|
||||
|
||||
void torrent_handle::queue_position_bottom() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(set_queue_position((std::numeric_limits<int>::max)()));
|
||||
}
|
||||
|
||||
void torrent_handle::set_tracker_login(std::string const& name
|
||||
, std::string const& password) const
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue