*** empty log message ***

This commit is contained in:
Arvid Norberg 2005-05-30 17:43:03 +00:00
parent e525456498
commit fbffae1981
11 changed files with 196 additions and 51 deletions

View File

@ -1237,6 +1237,8 @@ struct torrent_status
const std::vector<bool>* pieces; const std::vector<bool>* pieces;
size_type total_done; size_type total_done;
size_type total_wanted_done;
size_type total_wanted;
int num_seeds; int num_seeds;
float distributed_copies; float distributed_copies;
@ -1278,6 +1280,7 @@ is a pure seeder.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<p>When downloading, the progress is <tt class="docutils literal"><span class="pre">total_wanted_done</span></tt> / <tt class="docutils literal"><span class="pre">total_wanted</span></tt>.</p>
<p><tt class="docutils literal"><span class="pre">paused</span></tt> is set to true if the torrent is paused and false otherwise.</p> <p><tt class="docutils literal"><span class="pre">paused</span></tt> is set to true if the torrent is paused and false otherwise.</p>
<p><tt class="docutils literal"><span class="pre">next_announce</span></tt> is the time until the torrent will announce itself to the tracker. And <p><tt class="docutils literal"><span class="pre">next_announce</span></tt> is the time until the torrent will announce itself to the tracker. And
<tt class="docutils literal"><span class="pre">announce_interval</span></tt> is the time the tracker want us to wait until we announce ourself <tt class="docutils literal"><span class="pre">announce_interval</span></tt> is the time the tracker want us to wait until we announce ourself
@ -1311,6 +1314,11 @@ that are still downloading (incomplete) this torrent.</p>
<p><tt class="docutils literal"><span class="pre">total_done</span></tt> is the total number of bytes of the file(s) that we have. All <p><tt class="docutils literal"><span class="pre">total_done</span></tt> is the total number of bytes of the file(s) that we have. All
this does not necessarily has to be downloaded during this session (that's this does not necessarily has to be downloaded during this session (that's
<tt class="docutils literal"><span class="pre">total_download_payload</span></tt>).</p> <tt class="docutils literal"><span class="pre">total_download_payload</span></tt>).</p>
<p><tt class="docutils literal"><span class="pre">total_wanted_done</span></tt> is the number of bytes we have downloadd, only counting the
pieces that we actually want to download. i.e. excluding any pieces that we have but
are filtered as not wanted.</p>
<p><tt class="docutils literal"><span class="pre">total_wanted</span></tt> is the total number of bytes we want to download. This is also
excluding pieces that have been filtered.</p>
<p><tt class="docutils literal"><span class="pre">num_seeds</span></tt> is the number of peers that are seeding that this client is <p><tt class="docutils literal"><span class="pre">num_seeds</span></tt> is the number of peers that are seeding that this client is
currently connected to.</p> currently connected to.</p>
<p><tt class="docutils literal"><span class="pre">distributed_copies</span></tt> is the number of distributed copies of the torrent. <p><tt class="docutils literal"><span class="pre">distributed_copies</span></tt> is the number of distributed copies of the torrent.
@ -1375,15 +1383,16 @@ any combination of the enums above. The following table describes each flag:</p>
</colgroup> </colgroup>
<tbody valign="top"> <tbody valign="top">
<tr><td><tt class="docutils literal"><span class="pre">interesting</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">interesting</span></tt></td>
<td>we are interested in pieces from this peer.</td> <td><strong>we</strong> are interested in pieces from this peer.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">choked</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">choked</span></tt></td>
<td><strong>we</strong> have choked this peer.</td> <td><strong>we</strong> have choked this peer.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">remote_interested</span></tt> <tr><td><tt class="docutils literal"><span class="pre">remote_interested</span></tt></td>
<tt class="docutils literal"><span class="pre">remote_choked</span></tt></td> <td>the peer is interested in <strong>us</strong></td>
<td>means the same thing but that the peer is interested </tr>
in pieces from us and the peer has choked <strong>us</strong>.</td> <tr><td><tt class="docutils literal"><span class="pre">remote_choked</span></tt></td>
<td>the peer has choked <strong>us</strong>.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">support_extensions</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">support_extensions</span></tt></td>
<td>means that this peer supports the <td>means that this peer supports the
@ -1391,7 +1400,7 @@ in pieces from us and the peer has choked <strong>us</strong>.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">local_connection</span></tt></td> <tr><td><tt class="docutils literal"><span class="pre">local_connection</span></tt></td>
<td>The connection was initiated by us, the peer has a <td>The connection was initiated by us, the peer has a
listen port open, and that port is the same is in the listen port open, and that port is the same as in the
<a class="reference" href="#address">address</a> of this peer. If this flag is not set, this <a class="reference" href="#address">address</a> of this peer. If this flag is not set, this
peer connection was opened by this peer connecting to peer connection was opened by this peer connecting to
us.</td> us.</td>

View File

@ -1159,6 +1159,7 @@ It contains the following fields::
checking_files, checking_files,
connecting_to_tracker, connecting_to_tracker,
downloading, downloading,
finished,
seeding seeding
}; };
@ -1191,6 +1192,8 @@ It contains the following fields::
const std::vector<bool>* pieces; const std::vector<bool>* pieces;
size_type total_done; size_type total_done;
size_type total_wanted_done;
size_type total_wanted;
int num_seeds; int num_seeds;
float distributed_copies; float distributed_copies;
@ -1220,13 +1223,18 @@ current task is in the ``state`` member, it will be one of the following:
| |most torrents will be in most of the time. The progress | | |most torrents will be in most of the time. The progress |
| |meter will tell how much of the files that has been | | |meter will tell how much of the files that has been |
| |downloaded. | | |downloaded. |
| | | +--------------------------+----------------------------------------------------------+
|``finished`` |In this state the torrent has finished downloading but |
| |still doesn't have the entire torrent. i.e. some pieces |
| |are filtered and won't get downloaded. |
+--------------------------+----------------------------------------------------------+ +--------------------------+----------------------------------------------------------+
|``seeding`` |In this state the torrent has finished downloading and | |``seeding`` |In this state the torrent has finished downloading and |
| |is a pure seeder. | | |is a pure seeder. |
| | | | | |
+--------------------------+----------------------------------------------------------+ +--------------------------+----------------------------------------------------------+
When downloading, the progress is ``total_wanted_done`` / ``total_wanted``.
``paused`` is set to true if the torrent is paused and false otherwise. ``paused`` is set to true if the torrent is paused and false otherwise.
``next_announce`` is the time until the torrent will announce itself to the tracker. And ``next_announce`` is the time until the torrent will announce itself to the tracker. And
@ -1271,6 +1279,13 @@ that are still downloading (incomplete) this torrent.
this does not necessarily has to be downloaded during this session (that's this does not necessarily has to be downloaded during this session (that's
``total_download_payload``). ``total_download_payload``).
``total_wanted_done`` is the number of bytes we have downloadd, only counting the
pieces that we actually want to download. i.e. excluding any pieces that we have but
are filtered as not wanted.
``total_wanted`` is the total number of bytes we want to download. This is also
excluding pieces that have been filtered.
``num_seeds`` is the number of peers that are seeding that this client is ``num_seeds`` is the number of peers that are seeding that this client is
currently connected to. currently connected to.
@ -1333,18 +1348,19 @@ The ``flags`` attribute tells you in which state the peer is. It is set to
any combination of the enums above. The following table describes each flag: any combination of the enums above. The following table describes each flag:
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``interesting`` | we are interested in pieces from this peer. | | ``interesting`` | **we** are interested in pieces from this peer. |
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``choked`` | **we** have choked this peer. | | ``choked`` | **we** have choked this peer. |
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``remote_interested`` | means the same thing but that the peer is interested | | ``remote_interested`` | the peer is interested in **us** |
| ``remote_choked`` | in pieces from us and the peer has choked **us**. | +-------------------------+-------------------------------------------------------+
| ``remote_choked`` | the peer has choked **us**. |
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``support_extensions`` | means that this peer supports the | | ``support_extensions`` | means that this peer supports the |
| | `extension protocol`__. | | | `extension protocol`__. |
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``local_connection`` | The connection was initiated by us, the peer has a | | ``local_connection`` | The connection was initiated by us, the peer has a |
| | listen port open, and that port is the same is in the | | | listen port open, and that port is the same as in the |
| | address_ of this peer. If this flag is not set, this | | | address_ of this peer. If this flag is not set, this |
| | peer connection was opened by this peer connecting to | | | peer connection was opened by this peer connecting to |
| | us. | | | us. |

View File

@ -147,7 +147,7 @@ void clear()
#endif #endif
std::string to_string(float v, int width, int precision = 4) std::string to_string(float v, int width, int precision = 3)
{ {
std::stringstream s; std::stringstream s;
s.precision(precision); s.precision(precision);
@ -197,7 +197,7 @@ std::string add_suffix(float val)
for (int i = 0; i < num_prefix; ++i) for (int i = 0; i < num_prefix; ++i)
{ {
if (fabs(val) < 1000.f) if (fabs(val) < 1000.f)
return to_string(val, i==0?7:6) + prefix[i]; return to_string(val, i==0?5:4) + prefix[i];
val /= 1000.f; val /= 1000.f;
} }
return to_string(val, 6) + "PB"; return to_string(val, 6) + "PB";
@ -208,8 +208,9 @@ std::string progress_bar(float progress, int width)
std::vector<char> bar; std::vector<char> bar;
bar.reserve(width); bar.reserve(width);
std::fill_n(std::back_inserter(bar), progress * width, '#'); int progress_chars = progress * width + .5f;
std::fill_n(std::back_inserter(bar), width - (progress * width), '-'); std::fill_n(std::back_inserter(bar), progress_chars, '#');
std::fill_n(std::back_inserter(bar), width - progress_chars, '-');
return std::string(bar.begin(), bar.end()); return std::string(bar.begin(), bar.end());
} }
@ -217,7 +218,7 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
{ {
using namespace libtorrent; using namespace libtorrent;
out << " down up q r flags client block\n"; out << " down up q r flags block progress client \n";
for (std::vector<peer_info>::const_iterator i = peers.begin(); for (std::vector<peer_info>::const_iterator i = peers.begin();
i != peers.end(); ++i) i != peers.end(); ++i)
@ -238,17 +239,20 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
<< static_cast<const char*>((i->flags & peer_info::remote_interested)?"i":"_") << static_cast<const char*>((i->flags & peer_info::remote_interested)?"i":"_")
<< static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_") << static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_")
<< static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_") << static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_")
<< static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r") << " " << static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r") << " ";
<< identify_client(i->id);
if (i->downloading_piece_index >= 0) if (i->downloading_piece_index >= 0)
{ {
out << " " << progress_bar( out << progress_bar(
i->downloading_progress / static_cast<float>(i->downloading_total) i->downloading_progress / static_cast<float>(i->downloading_total)
, 15); , 15);
} }
else
{
out << progress_bar(0.f, 15);
}
out << "\n"; out << " " << identify_client(i->id) << "\n";
} }
} }
@ -328,6 +332,12 @@ int main(int argc, char* argv[])
handles.back().set_max_connections(100); handles.back().set_max_connections(100);
handles.back().set_max_uploads(-1); handles.back().set_max_uploads(-1);
handles.back().set_ratio(1.02f); handles.back().set_ratio(1.02f);
/*
for (int i = 0; i < t.num_pieces(); ++i)
{
handles.back().filter_piece(i, i % 2 == 0);
}
*/
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -446,6 +456,10 @@ int main(int argc, char* argv[])
--i; --i;
continue; continue;
} }
out << "name: ";
if (i->has_metadata()) out << i->get_torrent_info().name();
else out << "-";
out << "\n";
torrent_status s = i->status(); torrent_status s = i->status();
switch(s.state) switch(s.state)
@ -465,6 +479,9 @@ int main(int argc, char* argv[])
case torrent_status::downloading: case torrent_status::downloading:
out << "downloading "; out << "downloading ";
break; break;
case torrent_status::finished:
out << "finished ";
break;
case torrent_status::seeding: case torrent_status::seeding:
out << "seeding "; out << "seeding ";
break; break;
@ -483,9 +500,9 @@ int main(int argc, char* argv[])
out << "peers: " << s.num_peers << " " out << "peers: " << s.num_peers << " "
<< "seeds: " << s.num_seeds << " " << "seeds: " << s.num_seeds << " "
<< "distributed copies: " << s.distributed_copies << "\n"; << "distributed copies: " << s.distributed_copies << "\n";
out << "download:" << add_suffix(s.download_rate) << "/s " out << "download: " << add_suffix(s.download_rate) << "/s "
<< "(" << add_suffix(s.total_download) << ") " << "(" << add_suffix(s.total_download) << ") "
<< "upload:" << add_suffix(s.upload_rate) << "/s " << "upload: " << add_suffix(s.upload_rate) << "/s "
<< "(" << add_suffix(s.total_upload) << ") " << "(" << add_suffix(s.total_upload) << ") "
<< "ratio: " << ratio(s.total_payload_download, s.total_payload_upload) << "\n"; << "ratio: " << ratio(s.total_payload_download, s.total_payload_upload) << "\n";
out << "info-hash: " << i->info_hash() << "\n"; out << "info-hash: " << i->info_hash() << "\n";

View File

@ -199,6 +199,11 @@ namespace libtorrent
boost::optional<address> get_downloader(piece_block block) const; boost::optional<address> get_downloader(piece_block block) const;
// the number of filtered pieces we don't have
int num_filtered() const { return m_num_filtered; }
// the number of filtered pieces we already have
int num_have_filtered() const { return m_num_have_filtered; }
#ifndef NDEBUG #ifndef NDEBUG
// used in debug mode // used in debug mode
void integrity_check(const torrent* t = 0) const; void integrity_check(const torrent* t = 0) const;
@ -298,6 +303,14 @@ namespace libtorrent
int m_blocks_per_piece; int m_blocks_per_piece;
int m_blocks_in_last_piece; int m_blocks_in_last_piece;
// the number of filtered pieces that we don't already
// have. total_number_of_pieces - number_of_pieces_we_have
// - num_filtered is supposed to the number of pieces
// we still want to download
int m_num_filtered;
// the number of pieces we have that also are filtered
int m_num_have_filtered;
}; };
inline int piece_picker::blocks_in_piece(int index) const inline int piece_picker::blocks_in_piece(int index) const

View File

@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
@ -135,7 +136,7 @@ namespace libtorrent
stat statistics() const { return m_stat; } stat statistics() const { return m_stat; }
size_type bytes_left() const; size_type bytes_left() const;
size_type bytes_done() const; boost::tuple<size_type, size_type> bytes_done() const;
void pause(); void pause();
void resume(); void resume();

View File

@ -89,6 +89,8 @@ namespace libtorrent
, num_incomplete(-1) , num_incomplete(-1)
, pieces(0) , pieces(0)
, total_done(0) , total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, num_seeds(0) , num_seeds(0)
, distributed_copies(0.f) , distributed_copies(0.f)
, block_size(0) , block_size(0)
@ -101,6 +103,7 @@ namespace libtorrent
connecting_to_tracker, connecting_to_tracker,
downloading_metadata, downloading_metadata,
downloading, downloading,
finished,
seeding seeding
}; };
@ -150,8 +153,20 @@ namespace libtorrent
const std::vector<bool>* pieces; const std::vector<bool>* pieces;
// the number of bytes of the file we have // the number of bytes of the file we have
// including pieces that may have been filtered
// after we downloaded them
size_type total_done; size_type total_done;
// the number of bytes we have of those that we
// want. i.e. not counting bytes from pieces that
// are filtered as not wanted.
size_type total_wanted_done;
// the total number of bytes we want to download
// this may be smaller than the total torrent size
// in case any pieces are filtered as not wanted
size_type total_wanted;
// the number of peers this torrent is connected to // the number of peers this torrent is connected to
// that are seeding. // that are seeding.
int num_seeds; int num_seeds;

View File

@ -268,13 +268,12 @@ namespace libtorrent
// peer has, in a shuffled order // peer has, in a shuffled order
bool interesting = false; bool interesting = false;
for (std::vector<int>::iterator i = piece_list.begin(); for (std::vector<int>::iterator i = piece_list.begin();
i != piece_list.end(); i != piece_list.end(); ++i)
++i)
{ {
int index = *i; int index = *i;
m_torrent->peer_has(index); m_torrent->peer_has(index);
if (!m_torrent->have_piece(index) if (!m_torrent->have_piece(index)
&& m_torrent->picker().is_filtered(index)) && !m_torrent->picker().is_filtered(index))
interesting = true; interesting = true;
} }

View File

@ -59,6 +59,8 @@ namespace libtorrent
, m_downloading_piece_info(2) , m_downloading_piece_info(2)
, m_filtered_piece_info(2) , m_filtered_piece_info(2)
, m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece) , m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece)
, m_num_filtered(0)
, m_num_have_filtered(0)
{ {
assert(blocks_per_piece > 0); assert(blocks_per_piece > 0);
assert(total_num_blocks > 0); assert(total_num_blocks > 0);
@ -80,6 +82,7 @@ namespace libtorrent
std::fill(m_piece_map.begin(), m_piece_map.end(), piece_pos(0, piece_pos::we_have_index)); std::fill(m_piece_map.begin(), m_piece_map.end(), piece_pos(0, piece_pos::we_have_index));
} }
// pieces is a bitmask with the pieces we have
void piece_picker::files_checked( void piece_picker::files_checked(
const std::vector<bool>& pieces const std::vector<bool>& pieces
, const std::vector<downloading_piece>& unfinished) , const std::vector<downloading_piece>& unfinished)
@ -93,6 +96,11 @@ namespace libtorrent
{ {
if (*i) continue; if (*i) continue;
int index = static_cast<int>(i - pieces.begin()); int index = static_cast<int>(i - pieces.begin());
if (m_piece_map[index].filtered)
{
++m_num_filtered;
--m_num_have_filtered;
}
piece_list.push_back(index); piece_list.push_back(index);
} }
@ -149,11 +157,19 @@ namespace libtorrent
if (t != 0) if (t != 0)
assert((int)m_piece_map.size() == t->torrent_file().num_pieces()); assert((int)m_piece_map.size() == t->torrent_file().num_pieces());
int num_filtered = 0;
int num_have_filtered = 0;
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin(); for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin();
i != m_piece_map.end(); ++i) i != m_piece_map.end(); ++i)
{ {
int index = static_cast<int>(i - m_piece_map.begin()); int index = static_cast<int>(i - m_piece_map.begin());
if (i->filtered)
{
if (i->index != piece_pos::we_have_index)
++num_filtered;
else
++num_have_filtered;
}
if (t != 0) if (t != 0)
{ {
int actual_peer_count = 0; int actual_peer_count = 0;
@ -241,7 +257,8 @@ namespace libtorrent
assert(down == m_downloads.end()); assert(down == m_downloads.end());
} }
} }
assert(num_filtered == m_num_filtered);
assert(num_have_filtered == m_num_have_filtered);
} }
#endif #endif
@ -452,6 +469,11 @@ namespace libtorrent
assert(info_index != piece_pos::we_have_index); assert(info_index != piece_pos::we_have_index);
piece_pos& p = m_piece_map[index]; piece_pos& p = m_piece_map[index];
if (p.filtered)
{
--m_num_filtered;
++m_num_have_filtered;
}
remove(p.downloading, p.filtered, peer_count, info_index); remove(p.downloading, p.filtered, peer_count, info_index);
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();
@ -472,7 +494,14 @@ namespace libtorrent
if (p.filtered == 1) return; if (p.filtered == 1) return;
p.filtered = 1; p.filtered = 1;
if (p.index != piece_pos::we_have_index) if (p.index != piece_pos::we_have_index)
{
++m_num_filtered;
move(p.downloading, false, p.peer_count, p.index); move(p.downloading, false, p.peer_count, p.index);
}
else
{
++m_num_have_filtered;
}
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();
@ -493,7 +522,16 @@ namespace libtorrent
if (p.filtered == 0) return; if (p.filtered == 0) return;
p.filtered = 0; p.filtered = 0;
if (p.index != piece_pos::we_have_index) if (p.index != piece_pos::we_have_index)
{
--m_num_filtered;
assert(m_num_filtered >= 0);
move(p.downloading, true, p.peer_count, p.index); move(p.downloading, true, p.peer_count, p.index);
}
else
{
--m_num_have_filtered;
assert(m_num_have_filtered >= 0);
}
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();

View File

@ -188,9 +188,7 @@ namespace libtorrent { namespace detail
detail::piece_checker_data* checker_impl::find_torrent(sha1_hash const& info_hash) detail::piece_checker_data* checker_impl::find_torrent(sha1_hash const& info_hash)
{ {
for (std::deque<piece_checker_data>::iterator i for (std::deque<piece_checker_data>::iterator i
= m_torrents.begin(); = m_torrents.begin(); i != m_torrents.end(); ++i)
i != m_torrents.end();
++i)
{ {
if (i->info_hash == info_hash) return &(*i); if (i->info_hash == info_hash) return &(*i);
} }
@ -200,9 +198,7 @@ namespace libtorrent { namespace detail
void checker_impl::remove_torrent(sha1_hash const& info_hash) void checker_impl::remove_torrent(sha1_hash const& info_hash)
{ {
for (std::deque<piece_checker_data>::iterator i for (std::deque<piece_checker_data>::iterator i
= m_torrents.begin(); = m_torrents.begin(); i != m_torrents.end(); ++i)
i != m_torrents.end();
++i)
{ {
if (i->info_hash == info_hash) if (i->info_hash == info_hash)
{ {

View File

@ -364,16 +364,22 @@ namespace libtorrent
// if we don't have the metadata yet, we // if we don't have the metadata yet, we
// cannot tell how big the torrent is. // cannot tell how big the torrent is.
if (!valid_metadata()) return -1; if (!valid_metadata()) return -1;
return m_torrent_file.total_size() - bytes_done(); return m_torrent_file.total_size() - boost::get<0>(bytes_done());
} }
size_type torrent::bytes_done() const // the first value is the total number of bytes downloaded
// the second value is the number of bytes of those that haven't
// been filtered as not wanted we have downloaded
boost::tuple<size_type, size_type> torrent::bytes_done() const
{ {
if (!valid_metadata()) return 0; if (!valid_metadata()) return 0;
assert(m_picker.get()); assert(m_picker.get());
const int last_piece = m_torrent_file.num_pieces()-1; const int last_piece = m_torrent_file.num_pieces() - 1;
size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered())
* m_torrent_file.piece_length();
size_type total_done size_type total_done
= m_num_pieces * m_torrent_file.piece_length(); = m_num_pieces * m_torrent_file.piece_length();
@ -382,25 +388,28 @@ namespace libtorrent
// assumed all pieces were of equal size // assumed all pieces were of equal size
if (m_have_pieces[last_piece]) if (m_have_pieces[last_piece])
{ {
total_done -= m_torrent_file.piece_length(); int corr = m_torrent_file.piece_size(last_piece)
total_done += m_torrent_file.piece_size(last_piece); - m_torrent_file.piece_length();
total_done += corr;
if (!m_picker->is_filtered(last_piece))
wanted_done += corr;
} }
const std::vector<piece_picker::downloading_piece>& dl_queue const std::vector<piece_picker::downloading_piece>& dl_queue
= m_picker->get_download_queue(); = m_picker->get_download_queue();
const int blocks_per_piece = static_cast<int>(m_torrent_file.piece_length() / m_block_size); const int blocks_per_piece = static_cast<int>(
m_torrent_file.piece_length() / m_block_size);
for (std::vector<piece_picker::downloading_piece>::const_iterator i = for (std::vector<piece_picker::downloading_piece>::const_iterator i =
dl_queue.begin(); dl_queue.begin(); i != dl_queue.end(); ++i)
i != dl_queue.end();
++i)
{ {
int corr = 0;
assert(!m_have_pieces[i->index]); assert(!m_have_pieces[i->index]);
for (int j = 0; j < blocks_per_piece; ++j) for (int j = 0; j < blocks_per_piece; ++j)
{ {
total_done += (i->finished_blocks[j]) * m_block_size; corr += (i->finished_blocks[j]) * m_block_size;
} }
// correction if this was the last piece // correction if this was the last piece
@ -408,9 +417,12 @@ namespace libtorrent
if (i->index == last_piece if (i->index == last_piece
&& i->finished_blocks[m_picker->blocks_in_last_piece()-1]) && i->finished_blocks[m_picker->blocks_in_last_piece()-1])
{ {
total_done -= m_block_size; corr -= m_block_size;
total_done += m_torrent_file.piece_size(last_piece) % m_block_size; corr += m_torrent_file.piece_size(last_piece) % m_block_size;
} }
total_done += corr;
if (!m_picker->is_filtered(i->index))
wanted_done += corr;
} }
std::map<piece_block, int> downloading_piece; std::map<piece_block, int> downloading_piece;
@ -443,8 +455,12 @@ namespace libtorrent
} }
for (std::map<piece_block, int>::iterator i = downloading_piece.begin(); for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
i != downloading_piece.end(); ++i) i != downloading_piece.end(); ++i)
{
total_done += i->second; total_done += i->second;
return total_done; if (!m_picker->is_filtered(i->first.piece_index))
wanted_done += i->second;
}
return boost::make_tuple(total_done, wanted_done);
} }
void torrent::piece_failed(int index) void torrent::piece_failed(int index)
@ -562,10 +578,14 @@ namespace libtorrent
assert(index >= 0); assert(index >= 0);
assert(index < m_torrent_file.num_pieces()); assert(index < m_torrent_file.num_pieces());
// TODO: update peer's interesting-bit
if (filter) m_picker->mark_as_filtered(index); if (filter) m_picker->mark_as_filtered(index);
else m_picker->mark_as_unfiltered(index); else m_picker->mark_as_unfiltered(index);
} }
// TODO: add a function to set the filter with one call
bool torrent::is_piece_filtered(int index) const bool torrent::is_piece_filtered(int index) const
{ {
// this call is only valid on torrents with metadata // this call is only valid on torrents with metadata
@ -1050,7 +1070,7 @@ namespace libtorrent
st.num_complete = m_complete; st.num_complete = m_complete;
st.num_incomplete = m_incomplete; st.num_incomplete = m_incomplete;
st.paused = m_paused; st.paused = m_paused;
st.total_done = bytes_done(); boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
// payload transfer // payload transfer
st.total_payload_download = m_stat.total_payload_download(); st.total_payload_download = m_stat.total_payload_download();
@ -1102,8 +1122,27 @@ namespace libtorrent
// fill in status that depends on metadata // fill in status that depends on metadata
st.progress = st.total_done st.total_wanted = m_torrent_file.total_size();
/ static_cast<float>(m_torrent_file.total_size());
if (m_picker.get() && (m_picker->num_filtered() > 0
|| m_picker->num_have_filtered() > 0))
{
int filtered_pieces = m_picker->num_filtered()
+ m_picker->num_have_filtered();
int last_piece_index = m_torrent_file.num_pieces() - 1;
if (m_picker->is_filtered(last_piece_index))
{
st.total_wanted -= m_torrent_file.piece_size(last_piece_index);
--filtered_pieces;
}
st.total_wanted -= filtered_pieces * m_torrent_file.piece_length();
}
assert(st.total_wanted >= st.total_wanted_done);
st.progress = st.total_wanted_done
/ static_cast<float>(st.total_wanted);
st.pieces = &m_have_pieces; st.pieces = &m_have_pieces;
@ -1111,6 +1150,8 @@ namespace libtorrent
st.state = torrent_status::connecting_to_tracker; st.state = torrent_status::connecting_to_tracker;
else if (m_num_pieces == (int)m_have_pieces.size()) else if (m_num_pieces == (int)m_have_pieces.size())
st.state = torrent_status::seeding; st.state = torrent_status::seeding;
else if (st.total_wanted_done == st.total_wanted)
st.state = torrent_status::finished;
else else
st.state = torrent_status::downloading; st.state = torrent_status::downloading;

View File

@ -78,7 +78,7 @@ namespace libtorrent
{ {
void throw_invalid_handle() void throw_invalid_handle()
{ {
throw_invalid_handle(); throw invalid_handle();
} }
template<class Ret, class F> template<class Ret, class F>