use span<> to return the block_info for a piece (#1777)

use span<> to return the block_info for a piece to improve range checks and loops
This commit is contained in:
Arvid Norberg 2017-03-04 23:45:07 -05:00 committed by GitHub
parent 9f9376fc26
commit 8cf6e9e37c
6 changed files with 131 additions and 143 deletions

View File

@ -50,7 +50,7 @@ namespace libtorrent { namespace aux {
// pull in constructors from base class
using base::base;
auto operator[](IndexType idx) -> decltype(this->base::operator[](underlying_index()))
auto operator[](IndexType idx) const -> decltype(this->base::operator[](underlying_index()))
{
TORRENT_ASSERT(idx >= IndexType(0));
return this->base::operator[](std::size_t(static_cast<underlying_index>(idx)));
@ -64,13 +64,13 @@ namespace libtorrent { namespace aux {
template <typename U = underlying_index, typename Cond
= typename std::enable_if<std::is_signed<U>::value>::type>
typed_span<T> first(underlying_index n)
typed_span<T> first(underlying_index n) const
{
TORRENT_ASSERT(n >= 0);
return this->base::first(std::size_t(n));
}
typed_span<T> first(std::size_t n)
typed_span<T> first(std::size_t n) const
{
TORRENT_ASSERT(n <= std::size_t((std::numeric_limits<underlying_index>::max)()));
return this->base::first(n);
@ -78,13 +78,13 @@ namespace libtorrent { namespace aux {
template <typename U = underlying_index, typename Cond
= typename std::enable_if<std::is_signed<U>::value>::type>
typed_span<T> last(underlying_index n)
typed_span<T> last(underlying_index n) const
{
TORRENT_ASSERT(n >= 0);
return this->base::last(std::size_t(n));
}
typed_span<T> last(std::size_t n)
typed_span<T> last(std::size_t n) const
{
TORRENT_ASSERT(n <= std::size_t((std::numeric_limits<underlying_index>::max)()));
return this->base::last(n);
@ -92,7 +92,7 @@ namespace libtorrent { namespace aux {
template <typename U = underlying_index, typename Cond
= typename std::enable_if<std::is_signed<U>::value>::type>
typed_span<T> subspan(underlying_index offset)
typed_span<T> subspan(underlying_index offset) const
{
TORRENT_ASSERT(offset >= 0);
return this->base::subspan(std::size_t(offset));
@ -100,20 +100,20 @@ namespace libtorrent { namespace aux {
template <typename U = underlying_index, typename Cond
= typename std::enable_if<std::is_signed<U>::value>::type>
typed_span<T> subspan(underlying_index offset, underlying_index count)
typed_span<T> subspan(underlying_index offset, underlying_index count) const
{
TORRENT_ASSERT(offset >= 0);
TORRENT_ASSERT(count >= 0);
return this->base::subspan(std::size_t(offset), std::size_t(count));
}
typed_span<T> subspan(std::size_t offset)
typed_span<T> subspan(std::size_t offset) const
{
TORRENT_ASSERT(offset <= std::size_t((std::numeric_limits<underlying_index>::max)()));
return this->base::subspan(offset);
}
typed_span<T> subspan(std::size_t offset, std::size_t count)
typed_span<T> subspan(std::size_t offset, std::size_t count) const
{
TORRENT_ASSERT(offset <= std::size_t((std::numeric_limits<underlying_index>::max)()));
TORRENT_ASSERT(count <= std::size_t((std::numeric_limits<underlying_index>::max)()));

View File

@ -56,6 +56,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp"
#include "libtorrent/piece_block.hpp"
#include "libtorrent/aux_/vector.hpp"
#include "libtorrent/aux_/typed_span.hpp"
namespace libtorrent
{
@ -429,11 +430,12 @@ namespace libtorrent
// return the array of block_info objects for a given downloading_piece.
// this array has m_blocks_per_piece elements in it
block_info* blocks_for_piece(downloading_piece const& dp);
block_info const* blocks_for_piece(downloading_piece const& dp) const;
aux::typed_span<block_info const> blocks_for_piece(downloading_piece const& dp) const;
private:
aux::typed_span<block_info> mutable_blocks_for_piece(downloading_piece const& dp);
std::tuple<bool, bool, int, int> requested_from(
piece_picker::downloading_piece const& p
, int num_blocks_in_piece, torrent_peer* peer) const;

View File

@ -105,7 +105,7 @@ namespace libtorrent
return { data() + offset, count };
}
T& operator[](std::size_t const idx)
T& operator[](std::size_t const idx) const
{
TORRENT_ASSERT(idx < m_len);
return m_ptr[idx];

View File

@ -3053,14 +3053,13 @@ namespace libtorrent
#if TORRENT_USE_ASSERTS
if (t->has_picker())
{
const std::vector<piece_picker::downloading_piece>& q
std::vector<piece_picker::downloading_piece> const& q
= picker.get_download_queue();
for (std::vector<piece_picker::downloading_piece>::const_iterator
i = q.begin(), end(q.end()); i != end; ++i)
for (piece_picker::downloading_piece const& dp : q)
{
if (i->index != block_finished.piece_index) continue;
piece_picker::block_info* info = picker.blocks_for_piece(*i);
if (dp.index != block_finished.piece_index) continue;
auto const info = picker.blocks_for_piece(dp);
TORRENT_ASSERT(info[block_finished.block_index].state
== piece_picker::block_info::state_finished);
}

View File

@ -207,15 +207,14 @@ namespace libtorrent
TORRENT_ASSERT(int(ret.info_idx) * m_blocks_per_piece
+ m_blocks_per_piece <= int(m_block_info.size()));
block_info* info = blocks_for_piece(ret);
for (int i = 0; i < m_blocks_per_piece; ++i)
for (auto& info : mutable_blocks_for_piece(ret))
{
info[i].num_peers = 0;
info[i].state = block_info::state_none;
info[i].peer = nullptr;
info.num_peers = 0;
info.state = block_info::state_none;
info.peer = nullptr;
#if TORRENT_USE_ASSERTS
info[i].piece_index = piece;
info[i].peers.clear();
info.piece_index = piece;
info.peers.clear();
#endif
}
downloading_iter = m_downloads[download_state].insert(downloading_iter, ret);
@ -283,18 +282,18 @@ namespace libtorrent
*zero_prio = int(m_downloads[piece_pos::piece_zero_prio].size());
}
piece_picker::block_info* piece_picker::blocks_for_piece(
aux::typed_span<piece_picker::block_info> piece_picker::mutable_blocks_for_piece(
downloading_piece const& dp)
{
int idx = int(dp.info_idx) * m_blocks_per_piece;
TORRENT_ASSERT(idx + m_blocks_per_piece <= int(m_block_info.size()));
return &m_block_info[idx];
return { &m_block_info[idx], static_cast<std::size_t>(blocks_in_piece(dp.index)) };
}
piece_picker::block_info const* piece_picker::blocks_for_piece(
aux::typed_span<piece_picker::block_info const> piece_picker::blocks_for_piece(
downloading_piece const& dp) const
{
return const_cast<piece_picker*>(this)->blocks_for_piece(dp);
return const_cast<piece_picker*>(this)->mutable_blocks_for_piece(dp);
}
#if TORRENT_USE_INVARIANT_CHECKS
@ -313,12 +312,11 @@ namespace libtorrent
TORRENT_ASSERT(dp.index < next.index);
TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece
+ m_blocks_per_piece <= int(m_block_info.size()));
block_info const* info = blocks_for_piece(dp);
for (int j = 0; j < m_blocks_per_piece; ++j)
for (auto const& bl : blocks_for_piece(dp))
{
if (info[j].peer)
if (bl.peer)
{
torrent_peer* p = info[j].peer;
torrent_peer* p = bl.peer;
TORRENT_ASSERT(p->in_use);
TORRENT_ASSERT(p->connection == nullptr
|| static_cast<peer_connection*>(p->connection)->m_in_use);
@ -440,11 +438,10 @@ namespace libtorrent
TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece
+ m_blocks_per_piece <= int(m_block_info.size()));
#if TORRENT_USE_ASSERTS
block_info const* info = blocks_for_piece(dp);
for (int j = 0; j < m_blocks_per_piece; ++j)
for (auto const& bl : blocks_for_piece(dp))
{
if (!info[j].peer) continue;
torrent_peer* p = info[j].peer;
if (!bl.peer) continue;
torrent_peer* p = bl.peer;
TORRENT_ASSERT(p->in_use);
TORRENT_ASSERT(p->connection == nullptr
|| static_cast<peer_connection*>(p->connection)->m_in_use);
@ -467,32 +464,31 @@ namespace libtorrent
int num_finished = 0;
int num_writing = 0;
int num_open = 0;
block_info const* info = blocks_for_piece(dp);
for (int k = 0; k < num_blocks; ++k)
for (auto const& bl : blocks_for_piece(dp))
{
TORRENT_ASSERT(info[k].piece_index == dp.index);
TORRENT_ASSERT(info[k].peer == nullptr
|| info[k].peer->in_use);
TORRENT_ASSERT(bl.piece_index == dp.index);
TORRENT_ASSERT(bl.peer == nullptr
|| bl.peer->in_use);
if (info[k].state == block_info::state_finished)
if (bl.state == block_info::state_finished)
{
++num_finished;
TORRENT_ASSERT(info[k].num_peers == 0);
TORRENT_ASSERT(bl.num_peers == 0);
}
else if (info[k].state == block_info::state_requested)
else if (bl.state == block_info::state_requested)
{
++num_requested;
TORRENT_ASSERT(info[k].num_peers > 0);
TORRENT_ASSERT(bl.num_peers > 0);
}
else if (info[k].state == block_info::state_writing)
else if (bl.state == block_info::state_writing)
{
++num_writing;
TORRENT_ASSERT(info[k].num_peers == 0);
TORRENT_ASSERT(bl.num_peers == 0);
}
else if (info[k].state == block_info::state_none)
else if (bl.state == block_info::state_none)
{
++num_open;
TORRENT_ASSERT(info[k].num_peers == 0);
TORRENT_ASSERT(bl.num_peers == 0);
}
}
@ -2317,17 +2313,16 @@ get_out:
TORRENT_ASSERT(piece_priority(dp->index) > 0);
// fill in with blocks requested from other peers
// as backups
int const num_blocks_in_piece = blocks_in_piece(dp->index);
TORRENT_ASSERT(dp->requested > 0);
block_info const* binfo = blocks_for_piece(*dp);
for (int j = 0; j < num_blocks_in_piece; ++j)
int idx = -1;
for (auto const& info : blocks_for_piece(*dp))
{
block_info const& info = binfo[j];
++idx;
TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use);
TORRENT_ASSERT(info.piece_index == dp->index);
if (info.state != block_info::state_requested || info.peer == peer)
continue;
temp.push_back(piece_block(dp->index, j));
temp.push_back(piece_block(dp->index, idx));
}
// are we done?
if (!temp.empty())
@ -2358,15 +2353,14 @@ get_out:
&& piece_priority(i.index) != priority_levels - 1)
continue;
const int num_blocks_in_piece = blocks_in_piece(i.index);
block_info const* binfo = blocks_for_piece(i);
for (int j = 0; j < num_blocks_in_piece; ++j)
int idx = -1;
for (auto const& info : blocks_for_piece(i))
{
block_info const& info = binfo[j];
++idx;
TORRENT_ASSERT(info.piece_index == i.index);
if (info.state != block_info::state_none) continue;
auto k = std::find(interesting_blocks.begin(), interesting_blocks.end()
, piece_block(i.index, j));
, piece_block(i.index, idx));
if (k != interesting_blocks.end()) continue;
std::fprintf(stderr, "interesting blocks:\n");
@ -2379,7 +2373,7 @@ get_out:
for (auto const& l : m_downloads[piece_pos::piece_downloading])
{
block_info const* binfo2 = blocks_for_piece(l);
auto const binfo2 = blocks_for_piece(l);
std::fprintf(stderr, "%d : ", static_cast<int>(l.index));
const int cnt = blocks_in_piece(l.index);
for (int m = 0; m < cnt; ++m)
@ -2485,10 +2479,10 @@ get_out:
int contiguous_blocks = 0;
int max_contiguous = 0;
int first_block = 0;
block_info const* binfo = blocks_for_piece(p);
for (int j = 0; j < num_blocks_in_piece; ++j)
int idx = -1;
for (auto const& info : blocks_for_piece(p))
{
piece_picker::block_info const& info = binfo[j];
++idx;
TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use);
TORRENT_ASSERT(info.piece_index == p.index);
if (info.state == piece_picker::block_info::state_none)
@ -2499,7 +2493,7 @@ get_out:
if (contiguous_blocks > max_contiguous)
{
max_contiguous = contiguous_blocks;
first_block = j - contiguous_blocks;
first_block = idx - contiguous_blocks;
}
contiguous_blocks = 0;
if (info.peer != peer)
@ -2631,7 +2625,7 @@ get_out:
// pieces that only they have downloaded/requested from
if ((options & on_parole) && !exclusive) return num_blocks;
block_info const* binfo = blocks_for_piece(dp);
auto const binfo = blocks_for_piece(dp);
// we prefer whole blocks, but there are other peers
// downloading from this piece and there aren't enough contiguous blocks
@ -2648,7 +2642,7 @@ get_out:
for (int j = 0; j < num_blocks_in_piece; ++j)
{
// ignore completed blocks and already requested blocks
int block_idx = (j + first_block) % num_blocks_in_piece;
int const block_idx = (j + first_block) % num_blocks_in_piece;
block_info const& info = binfo[block_idx];
TORRENT_ASSERT(info.piece_index == dp.index);
if (info.state != block_info::state_none) continue;
@ -2660,7 +2654,7 @@ get_out:
for (int j = 0; j < num_blocks_in_piece; ++j)
{
// ignore completed blocks and already requested blocks
int block_idx = (j + first_block) % num_blocks_in_piece;
int const block_idx = (j + first_block) % num_blocks_in_piece;
block_info const& info = binfo[block_idx];
TORRENT_ASSERT(info.piece_index == dp.index);
if (info.state != block_info::state_none) continue;
@ -2749,17 +2743,16 @@ get_out:
std::vector<downloading_piece>::const_iterator i = find_dl_piece(state, index);
TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(int(i->finished) <= m_blocks_per_piece);
int max_blocks = blocks_in_piece(index);
int const max_blocks = blocks_in_piece(index);
if (int(i->finished) + int(i->writing) < max_blocks) return false;
TORRENT_ASSERT(int(i->finished) + int(i->writing) == max_blocks);
#if TORRENT_USE_INVARIANT_CHECKS
block_info const* info = blocks_for_piece(*i);
for (int k = 0; k < max_blocks; ++k)
for (auto const& info : blocks_for_piece(*i))
{
TORRENT_ASSERT(info[k].piece_index == index);
TORRENT_ASSERT(info[k].state == block_info::state_finished
|| info[k].state == block_info::state_writing);
TORRENT_ASSERT(info.piece_index == index);
TORRENT_ASSERT(info.state == block_info::state_finished
|| info.state == block_info::state_writing);
}
#endif
@ -2905,7 +2898,7 @@ get_out:
TORRENT_ASSERT(i != m_downloads[state].end());
block_info const* info = blocks_for_piece(*i);
auto const info = blocks_for_piece(*i);
TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return info[block.block_index].state == block_info::state_requested;
}
@ -2923,7 +2916,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end());
block_info const* info = blocks_for_piece(*i);
auto const info = blocks_for_piece(*i);
TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return info[block.block_index].state == block_info::state_finished
|| info[block.block_index].state == block_info::state_writing;
@ -2942,7 +2935,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info const* info = blocks_for_piece(*i);
auto const info = blocks_for_piece(*i);
TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return info[block.block_index].state == block_info::state_finished;
}
@ -2981,7 +2974,7 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
auto const dp = add_download_piece(block.piece_index);
block_info* binfo = blocks_for_piece(*dp);
auto const binfo = mutable_blocks_for_piece(*dp);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(info.piece_index == block.piece_index);
info.state = block_info::state_requested;
@ -3005,7 +2998,7 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(info.piece_index == block.piece_index);
if (info.state == block_info::state_writing
@ -3068,7 +3061,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info const* binfo = blocks_for_piece(*i);
auto const binfo = blocks_for_piece(*i);
block_info const& info = binfo[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3126,7 +3119,7 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
auto const dp = add_download_piece(block.piece_index);
block_info* binfo = blocks_for_piece(*dp);
auto const binfo = mutable_blocks_for_piece(*dp);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3146,7 +3139,7 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
@ -3233,7 +3226,7 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(state, block.piece_index);
if (i == m_downloads[state].end()) return;
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3300,7 +3293,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
if (info.state == block_info::state_finished) return;
@ -3370,7 +3363,7 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
auto const dp = add_download_piece(block.piece_index);
block_info* binfo = blocks_for_piece(*dp);
auto const binfo = mutable_blocks_for_piece(*dp);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3392,7 +3385,7 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(info.piece_index == block.piece_index);
@ -3451,7 +3444,7 @@ get_out:
std::vector<downloading_piece>::const_iterator i
= find_dl_piece(state, index);
TORRENT_ASSERT(i != m_downloads[state].end());
block_info const* binfo = blocks_for_piece(*i);
auto const binfo = blocks_for_piece(*i);
for (int j = 0; j != num_blocks; ++j)
{
TORRENT_ASSERT(binfo[j].peer == nullptr
@ -3469,7 +3462,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(block.block_index != piece_block::invalid.block_index);
block_info const* binfo = blocks_for_piece(*i);
auto const binfo = blocks_for_piece(*i);
TORRENT_ASSERT(binfo[block.block_index].piece_index == block.piece_index);
if (binfo[block.block_index].state == block_info::state_none)
return nullptr;
@ -3502,7 +3495,7 @@ get_out:
, block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end());
block_info* binfo = blocks_for_piece(*i);
auto const binfo = mutable_blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use);
TORRENT_ASSERT(info.piece_index == block.piece_index);

View File

@ -1816,7 +1816,7 @@ namespace libtorrent
for (auto const& p : dq)
{
int num_blocks = m_picker->blocks_in_piece(p.index);
int const num_blocks = m_picker->blocks_in_piece(p.index);
if (p.finished < num_blocks) continue;
have_pieces.push_back(p.index);
}
@ -1855,30 +1855,25 @@ namespace libtorrent
{
std::vector<std::shared_ptr<torrent>> ts = m_ses.find_collection(c);
for (std::vector<std::shared_ptr<torrent>>::iterator k = ts.begin()
, end2(ts.end()); k != end2; ++k)
for (auto const& t : ts)
{
// Only attempt to reuse files from torrents that are seeding.
// TODO: this could be optimized by looking up which files are
// complete and just look at those
if (!(*k)->is_seed()) continue;
if (!t->is_seed()) continue;
res.match((*k)->get_torrent_copy(), (*k)->save_path());
res.match(t->get_torrent_copy(), t->save_path());
}
}
std::vector<resolve_links::link_t> const& l = res.get_links();
if (!l.empty())
{
for (std::vector<resolve_links::link_t>::const_iterator i = l.begin()
, end(l.end()); i != end; ++i)
for (auto const& i : l)
{
if (!i->ti) continue;
torrent_info const& ti = *i->ti;
std::string const& save_path = i->save_path;
links.push_back(combine_path(save_path
, ti.files().file_path(i->file_idx)));
if (!i.ti) continue;
links.push_back(combine_path(i.save_path
, i.ti->files().file_path(i.file_idx)));
}
}
}
@ -3549,8 +3544,6 @@ namespace libtorrent
std::vector<piece_picker::downloading_piece> dl_queue
= m_picker->get_download_queue();
const int blocks_per_piece = (piece_size + block_size() - 1) / block_size();
// look at all unfinished pieces and add the completed
// blocks to our 'done' counter
for (auto i = dl_queue.begin(); i != dl_queue.end(); ++i)
@ -3566,20 +3559,21 @@ namespace libtorrent
, [index](piece_picker::downloading_piece const& p) { return p.index == index; }) == 0);
#endif
piece_picker::block_info* info = m_picker->blocks_for_piece(*i);
for (int j = 0; j < blocks_per_piece; ++j)
int idx = -1;
for (auto const& info : m_picker->blocks_for_piece(*i))
{
++idx;
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j))
== (info[j].state == piece_picker::block_info::state_finished));
TORRENT_ASSERT(m_picker->is_finished(piece_block(index, idx))
== (info.state == piece_picker::block_info::state_finished));
#endif
if (info[j].state == piece_picker::block_info::state_finished)
if (info.state == piece_picker::block_info::state_finished)
{
corr += block_bytes_wanted(piece_block(index, j));
corr += block_bytes_wanted(piece_block(index, idx));
}
TORRENT_ASSERT(corr >= 0);
TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece()
|| info[j].state != piece_picker::block_info::state_finished);
TORRENT_ASSERT(index != last_piece || idx < m_picker->blocks_in_last_piece()
|| info.state != piece_picker::block_info::state_finished);
}
st.total_done += corr;
@ -3642,10 +3636,9 @@ namespace libtorrent
for (auto const& dp : dl_queue)
{
std::fprintf(stderr, " %d ", static_cast<int>(dp.index));
piece_picker::block_info* info = m_picker->blocks_for_piece(dp);
for (int j = 0; j < blocks_per_piece; ++j)
for (auto const& info : m_picker->blocks_for_piece(dp))
{
char const* state = info[j].state
char const* state = info.state
== piece_picker::block_info::state_finished ? "1" : "0";
fputs(state, stderr);
}
@ -6029,7 +6022,7 @@ namespace libtorrent
int const num_bitmask_bytes
= std::max(num_blocks_per_piece / 8, 1);
piece_picker::block_info const* info = m_picker->blocks_for_piece(dp);
auto const info = m_picker->blocks_for_piece(dp);
for (int j = 0; j < num_bitmask_bytes; ++j)
{
char v = 0;
@ -6355,24 +6348,25 @@ namespace libtorrent
TORRENT_ASSERT(counter * blocks_per_piece + pi.blocks_in_piece <= int(blk.size()));
pi.blocks = &blk[std::size_t(counter * blocks_per_piece)];
int const piece_size = torrent_file().piece_size(i->index);
piece_picker::block_info const* info = m_picker->blocks_for_piece(*i);
for (int j = 0; j < pi.blocks_in_piece; ++j)
int idx = -1;
for (auto const& info : m_picker->blocks_for_piece(*i))
{
block_info& bi = pi.blocks[j];
bi.state = info[j].state;
bi.block_size = j < pi.blocks_in_piece - 1
++idx;
block_info& bi = pi.blocks[idx];
bi.state = info.state;
bi.block_size = idx < pi.blocks_in_piece - 1
? aux::numeric_cast<std::uint32_t>(block_size())
: aux::numeric_cast<std::uint32_t>(piece_size - (j * block_size()));
: aux::numeric_cast<std::uint32_t>(piece_size - (idx * block_size()));
bool complete = bi.state == block_info::writing
|| bi.state == block_info::finished;
if (info[j].peer == nullptr)
if (info.peer == nullptr)
{
bi.set_peer(tcp::endpoint());
bi.bytes_progress = complete ? bi.block_size : 0;
}
else
{
torrent_peer* tp = info[j].peer;
torrent_peer* tp = info.peer;
TORRENT_ASSERT(tp->in_use);
if (tp->connection)
{
@ -6382,7 +6376,7 @@ namespace libtorrent
if (bi.state == block_info::requested)
{
auto pbp = peer->downloading_piece_progress();
if (pbp.piece_index == i->index && pbp.block_index == j)
if (pbp.piece_index == i->index && pbp.block_index == idx)
{
bi.bytes_progress = aux::numeric_cast<std::uint32_t>(pbp.bytes_downloaded);
TORRENT_ASSERT(bi.bytes_progress <= bi.block_size);
@ -6404,7 +6398,7 @@ namespace libtorrent
}
}
pi.blocks[j].num_peers = info[j].num_peers;
pi.blocks[idx].num_peers = info.num_peers;
}
pi.piece_index = i->index;
queue->push_back(pi);
@ -9405,29 +9399,29 @@ namespace libtorrent
TORRENT_ALLOCA(busy_blocks, busy_block_t, blocks_in_piece);
int busy_count = 0;
piece_picker::block_info const* info = picker->blocks_for_piece(pi);
// pick busy blocks from the piece
for (int k = 0; k < blocks_in_piece; ++k)
int idx = -1;
for (auto const& info : picker->blocks_for_piece(pi))
{
++idx;
// only consider blocks that have been requested
// and we're still waiting for them
if (info[k].state != piece_picker::block_info::state_requested)
if (info.state != piece_picker::block_info::state_requested)
continue;
piece_block b(piece, k);
piece_block b(piece, idx);
// only allow a single additional request per block, in order
// to spread it out evenly across all stalled blocks
if (int(info[k].num_peers) > timed_out)
if (int(info.num_peers) > timed_out)
continue;
busy_blocks[busy_count].peers = info[k].num_peers;
busy_blocks[busy_count].index = k;
busy_blocks[busy_count].peers = info.num_peers;
busy_blocks[busy_count].index = idx;
++busy_count;
#if TORRENT_DEBUG_STREAMING > 1
std::printf(" [%d (%d)]", b.block_index, info[k].num_peers);
std::printf(" [%d (%d)]", b.block_index, info.num_peers);
#endif
}
#if TORRENT_DEBUG_STREAMING > 1
@ -10249,14 +10243,14 @@ namespace libtorrent
std::int64_t offset = std::int64_t(static_cast<int>(dp.index))
* m_torrent_file->piece_length();
file_index_t file = fs.file_index_at_offset(offset);
int num_blocks = m_picker->blocks_in_piece(dp.index);
piece_picker::block_info const* info = m_picker->blocks_for_piece(dp);
for (int k = 0; k < num_blocks; ++k)
int idx = -1;
for (auto const& info : m_picker->blocks_for_piece(dp))
{
++idx;
TORRENT_ASSERT(file < fs.end_file());
TORRENT_ASSERT(offset == std::int64_t(static_cast<int>(dp.index))
* m_torrent_file->piece_length()
+ k * block_size());
+ idx * block_size());
TORRENT_ASSERT(offset < m_torrent_file->total_size());
while (offset >= fs.file_offset(file) + fs.file_size(file))
{
@ -10266,21 +10260,21 @@ namespace libtorrent
std::int64_t block = block_size();
if (info[k].state == piece_picker::block_info::state_none)
if (info.state == piece_picker::block_info::state_none)
{
offset += block;
continue;
}
if (info[k].state == piece_picker::block_info::state_requested)
if (info.state == piece_picker::block_info::state_requested)
{
block = 0;
torrent_peer* p = info[k].peer;
torrent_peer* p = info.peer;
if (p != nullptr && p->connection)
{
peer_connection* peer = static_cast<peer_connection*>(p->connection);
auto pbp = peer->downloading_piece_progress();
if (pbp.piece_index == dp.index && pbp.block_index == k)
if (pbp.piece_index == dp.index && pbp.block_index == idx)
block = pbp.bytes_downloaded;
TORRENT_ASSERT(block <= block_size());
}
@ -10318,7 +10312,7 @@ namespace libtorrent
offset += left_over;
TORRENT_ASSERT(offset == std::int64_t(static_cast<int>(dp.index))
* m_torrent_file->piece_length()
+ (k + 1) * block_size());
+ (idx + 1) * block_size());
}
else
{