completed queuing. It is now possible to change and query queue position of torrents.

This commit is contained in:
Arvid Norberg 2008-05-29 03:37:19 +00:00
parent 63cf889be4
commit 31c9d378f5
10 changed files with 858 additions and 653 deletions

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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
-------

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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
{