diff --git a/libtorrent/include/libtorrent/stat.hpp b/libtorrent/include/libtorrent/stat.hpp index 8ef8da1b4..2424d5d6c 100755 --- a/libtorrent/include/libtorrent/stat.hpp +++ b/libtorrent/include/libtorrent/stat.hpp @@ -131,6 +131,8 @@ namespace libtorrent // transfers from earlier connections. void add_stat(size_type downloaded, size_type uploaded) { + assert(downloaded >= 0); + assert(uploaded >= 0); m_total_download_payload += downloaded; m_total_upload_payload += uploaded; } diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp index 6fa8d1082..4bc33f85d 100755 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ b/libtorrent/include/libtorrent/torrent_handle.hpp @@ -210,7 +210,15 @@ namespace libtorrent { none, requested, writing, finished }; tcp::endpoint peer; + // number of bytes downloaded in this block + unsigned bytes_progress:16; + // the total number of bytes in this block + unsigned block_size:16; + // the state this block is in (see block_state_t) unsigned state:2; + // the number of peers that has requested this block + // typically 0 or 1. If > 1, this block is in + // end game mode unsigned num_peers:14; }; diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index 5bdb32ca2..7a4fc50c5 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -267,6 +267,7 @@ namespace libtorrent continue; } + assert(p.num_peers(*i) == 0); // ok, we found a piece that's not being downloaded // by somebody else. request it from this peer // and return @@ -279,7 +280,7 @@ namespace libtorrent // blocks as well, we cannot download anything // more from this peer. - if (busy_pieces.empty()) + if (busy_pieces.empty() || num_requests == 0) { c.send_block_requests(); return; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 6ed6dd65a..b4a5efcd1 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2330,14 +2330,30 @@ namespace libtorrent // size_type download = m_stat.total_payload_download(); // size_type done = boost::get<0>(bytes_done()); // assert(download >= done - m_initial_done); + std::map num_requests; for (const_peer_iterator i = begin(); i != end(); ++i) { peer_connection const& p = *i->second; + for (std::deque::const_iterator i = p.request_queue().begin() + , end(p.request_queue().end()); i != end; ++i) + ++num_requests[*i]; + for (std::deque::const_iterator i = p.download_queue().begin() + , end(p.download_queue().end()); i != end; ++i) + ++num_requests[*i]; torrent* associated_torrent = p.associated_torrent().lock().get(); if (associated_torrent != this) assert(false); } + if (has_picker()) + { + for (std::map::iterator i = num_requests.begin() + , end(num_requests.end()); i != end; ++i) + { + assert(m_picker->num_peers(i->first) == i->second); + } + } + if (valid_metadata()) { assert(m_abort || int(m_have_pieces.size()) == m_torrent_file.num_pieces()); diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index 00877aa16..10e1172fa 100755 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -765,27 +765,61 @@ namespace libtorrent const std::vector& q = p.get_download_queue(); + int block_size = t->block_size(); + for (std::vector::const_iterator i = q.begin(); i != q.end(); ++i) { partial_piece_info pi; pi.piece_state = (partial_piece_info::state_t)i->state; pi.blocks_in_piece = p.blocks_in_piece(i->index); + int piece_size = t->torrent_file().piece_size(i->index); for (int j = 0; j < pi.blocks_in_piece; ++j) { + block_info& bi = pi.blocks[j]; + bi.state = i->info[j].state; + bi.block_size = j < pi.blocks_in_piece - 1 ? block_size + : piece_size - (j * block_size); + bool complete = bi.state == block_info::writing + || bi.state == block_info::finished; if (i->info[j].peer == 0) - pi.blocks[j].peer = tcp::endpoint(); + { + bi.peer = tcp::endpoint(); + bi.bytes_progress = complete ? bi.block_size : 0; + } else { policy::peer* p = static_cast(i->info[j].peer); if (p->connection) - pi.blocks[j].peer = p->connection->remote(); + { + bi.peer = p->connection->remote(); + if (bi.state == block_info::requested) + { + boost::optional pbp + = p->connection->downloading_piece_progress(); + if (pbp && pbp->piece_index == i->index && pbp->block_index == j) + { + bi.bytes_progress = pbp->bytes_downloaded; + assert(bi.bytes_progress <= bi.block_size); + } + else + { + bi.bytes_progress = 0; + } + } + else + { + bi.bytes_progress = complete ? bi.block_size : 0; + } + } else - pi.blocks[j].peer = p->ip; + { + bi.peer = p->ip; + bi.bytes_progress = complete ? bi.block_size : 0; + } } pi.blocks[j].num_peers = i->info[j].num_peers; - pi.blocks[j].state = i->info[j].state; } pi.piece_index = i->index; queue.push_back(pi);