optimize block_info allocation and downloading_piece size in piece_picker

This commit is contained in:
Arvid Norberg 2015-02-14 21:32:41 +00:00
parent e15e5fd80a
commit 2fdb7499fa
5 changed files with 244 additions and 208 deletions

View File

@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
@ -160,7 +161,8 @@ namespace libtorrent
struct downloading_piece struct downloading_piece
{ {
downloading_piece() : info(NULL), index(-1) downloading_piece() : index(UINT32_MAX)
, info_idx(UINT16_MAX)
, finished(0) , finished(0)
, passed_hash_check(0) , passed_hash_check(0)
, writing(0) , writing(0)
@ -170,15 +172,14 @@ namespace libtorrent
bool operator<(downloading_piece const& rhs) const { return index < rhs.index; } bool operator<(downloading_piece const& rhs) const { return index < rhs.index; }
// info about each block
// this is a pointer into the m_block_info
// vector owned by the piece_picker
// TODO: 2 if we could make this an index into m_block_info instead
// we would save at least 4 or 5 bytes
block_info* info;
// the index of the piece // the index of the piece
int index; boost::uint32_t index;
// info about each block in this piece. this is an index into the
// m_block_info array, when multiplied by m_blocks_per_piece.
// The m_blocks_per_piece following entries contain information about
// all blocks in this piece.
boost::uint16_t info_idx;
// the number of blocks in the finished state // the number of blocks in the finished state
boost::uint16_t finished:15; boost::uint16_t finished:15;
@ -472,10 +473,19 @@ namespace libtorrent
void set_num_pad_files(int n) { m_num_pad_files = n; } void set_num_pad_files(int n) { m_num_pad_files = n; }
// 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;
private: private:
friend struct piece_pos; friend struct piece_pos;
boost::tuple<bool, bool, int, int> requested_from(
piece_picker::downloading_piece const& p
, int num_blocks_in_piece, void* peer) const;
bool can_pick(int piece, bitfield const& bitmask) const; bool can_pick(int piece, bitfield const& bitmask) const;
bool is_piece_free(int piece, bitfield const& bitmask) const; bool is_piece_free(int piece, bitfield const& bitmask) const;
std::pair<int, int> expand_piece(int piece, int whole_pieces std::pair<int, int> expand_piece(int piece, int whole_pieces
@ -518,7 +528,7 @@ namespace libtorrent
// this is not a new download category/download list bucket. // this is not a new download category/download list bucket.
// it still goes into the piece_downloading bucket. However, // it still goes into the piece_downloading bucket. However,
// it indicates that this piece only has outstanding requests // it indicates that this piece only has outstanding requests
// form reverse peers. This is to de-prioritize it somewhat // from reverse peers. This is to de-prioritize it somewhat
piece_downloading_reverse, piece_downloading_reverse,
piece_full_reverse piece_full_reverse
}; };
@ -778,12 +788,17 @@ namespace libtorrent
// piece_downloading). // piece_downloading).
std::vector<downloading_piece> m_downloads[piece_pos::num_download_categories]; std::vector<downloading_piece> m_downloads[piece_pos::num_download_categories];
// this holds the information of the // this holds the information of the blocks in partially downloaded
// blocks in partially downloaded pieces. // pieces. the downloading_piece::info index point into this vector for
// the downloading_piece::info pointers // its storage
// point into this vector for its storage
std::vector<block_info> m_block_info; std::vector<block_info> m_block_info;
// these are block ranges in m_block_info that are free. The numbers
// in here, when multiplied by m_blocks_per_piece is the index to the
// first block in the range that's free to use by a new downloading_piece.
// this is a free-list.
std::vector<boost::uint16_t> m_free_block_infos;
boost::uint16_t m_blocks_per_piece; boost::uint16_t m_blocks_per_piece;
boost::uint16_t m_blocks_in_last_piece; boost::uint16_t m_blocks_in_last_piece;

View File

@ -679,7 +679,7 @@ namespace libtorrent
void get_full_peer_list(std::vector<peer_list_entry>& v) const; void get_full_peer_list(std::vector<peer_list_entry>& v) const;
void get_peer_info(std::vector<peer_info>& v); void get_peer_info(std::vector<peer_info>& v);
void get_download_queue(std::vector<partial_piece_info>* queue); void get_download_queue(std::vector<partial_piece_info>* queue) const;
void refresh_explicit_cache(int cache_size); void refresh_explicit_cache(int cache_size);
@ -971,6 +971,11 @@ namespace libtorrent
TORRENT_ASSERT(m_picker.get()); TORRENT_ASSERT(m_picker.get());
return *m_picker; return *m_picker;
} }
piece_picker const& picker() const
{
TORRENT_ASSERT(m_picker.get());
return *m_picker;
}
void need_picker(); void need_picker();
bool has_picker() const bool has_picker() const
{ {

View File

@ -2936,7 +2936,9 @@ namespace libtorrent
{ {
if (i->index != block_finished.piece_index) continue; if (i->index != block_finished.piece_index) continue;
piece_picker::downloading_piece const& p = *i; piece_picker::downloading_piece const& p = *i;
TORRENT_ASSERT(p.info[block_finished.block_index].state == piece_picker::block_info::state_finished); piece_picker::block_info* info = picker.blocks_for_piece(p);
TORRENT_ASSERT(info[block_finished.block_index].state
== piece_picker::block_info::state_finished);
} }
} }
#endif #endif

View File

@ -152,12 +152,13 @@ namespace libtorrent
int state = m_piece_map[index].download_queue(); int state = m_piece_map[index].download_queue();
if (state != piece_pos::piece_open) if (state != piece_pos::piece_open)
{ {
// TODO: 3 we need a different type to return to the outside here
std::vector<downloading_piece>::const_iterator piece = find_dl_piece(state, index); std::vector<downloading_piece>::const_iterator piece = find_dl_piece(state, index);
TORRENT_ASSERT(piece != m_downloads[state].end()); TORRENT_ASSERT(piece != m_downloads[state].end());
st = *piece; st = *piece;
return; return;
} }
st.info = 0; st.info_idx = 0;
st.index = index; st.index = index;
st.writing = 0; st.writing = 0;
st.requested = 0; st.requested = 0;
@ -190,30 +191,22 @@ namespace libtorrent
check_piece_state(); check_piece_state();
#endif #endif
int num_downloads = 0; int block_index;
for (int k = 0; k < piece_pos::num_download_categories; ++k)
num_downloads += m_downloads[k].size();
int block_index = num_downloads * m_blocks_per_piece; if (m_free_block_infos.empty())
if (int(m_block_info.size()) < block_index + m_blocks_per_piece)
{ {
block_info* base = NULL; // we need to allocate more space in m_block_info
if (!m_block_info.empty()) base = &m_block_info[0]; block_index = m_block_info.size() / m_blocks_per_piece;
m_block_info.resize(block_index + m_blocks_per_piece); TORRENT_ASSERT((m_block_info.size() % m_blocks_per_piece) == 0);
if (base != NULL && &m_block_info[0] != base) m_block_info.resize(m_block_info.size() + m_blocks_per_piece);
{
for (int k = 0; k < piece_pos::num_download_categories; ++k)
{
// this means the memory was reallocated, update the pointers
for (int i = 0; i < int(m_downloads[k].size()); ++i)
{
TORRENT_ASSERT(m_downloads[k][i].info >= base);
TORRENT_ASSERT(m_downloads[k][i].info < base + m_block_info.size());
m_downloads[k][i].info = &m_block_info[m_downloads[k][i].info - base];
}
}
}
} }
else
{
// there is already free space in m_block_info, grab one range
block_index = m_free_block_infos.back();
m_free_block_infos.pop_back();
}
// always insert into bucket 0 (piece_downloading) // always insert into bucket 0 (piece_downloading)
downloading_piece ret; downloading_piece ret;
ret.index = piece; ret.index = piece;
@ -222,24 +215,28 @@ namespace libtorrent
= std::lower_bound(m_downloads[download_state].begin() = std::lower_bound(m_downloads[download_state].begin()
, m_downloads[download_state].end(), ret); , m_downloads[download_state].end(), ret);
TORRENT_ASSERT(i == m_downloads[download_state].end() || i->index != piece); TORRENT_ASSERT(i == m_downloads[download_state].end() || i->index != piece);
ret.info = &m_block_info[block_index]; TORRENT_ASSERT(block_index >= 0);
TORRENT_ASSERT(ret.info >= &m_block_info[0]); TORRENT_ASSERT(block_index < UINT16_MAX);
TORRENT_ASSERT(ret.info < &m_block_info[0] + m_block_info.size()); ret.info_idx = block_index;
TORRENT_ASSERT(int(ret.info_idx) * m_blocks_per_piece
+ m_blocks_per_piece <= m_block_info.size());
#ifdef TORRENT_USE_VALGRIND #ifdef TORRENT_USE_VALGRIND
VALGRIND_CHECK_VALUE_IS_DEFINED(piece); VALGRIND_CHECK_VALUE_IS_DEFINED(piece);
VALGRIND_CHECK_VALUE_IS_DEFINED(block_index); VALGRIND_CHECK_VALUE_IS_DEFINED(block_index);
#endif #endif
block_info* info = blocks_for_piece(ret);
for (int i = 0; i < m_blocks_per_piece; ++i) for (int i = 0; i < m_blocks_per_piece; ++i)
{ {
ret.info[i].num_peers = 0; info[i].num_peers = 0;
ret.info[i].state = block_info::state_none; info[i].state = block_info::state_none;
ret.info[i].peer = 0; info[i].peer = 0;
#ifdef TORRENT_USE_VALGRIND #ifdef TORRENT_USE_VALGRIND
VALGRIND_CHECK_VALUE_IS_DEFINED(ret.info[i].peer); VALGRIND_CHECK_VALUE_IS_DEFINED(info[i].peer);
#endif #endif
#if TORRENT_USE_ASSERTS #if TORRENT_USE_ASSERTS
ret.info[i].piece_index = piece; info[i].piece_index = piece;
ret.info[i].peers.clear(); info[i].peers.clear();
#endif #endif
} }
#ifdef TORRENT_USE_VALGRIND #ifdef TORRENT_USE_VALGRIND
@ -267,30 +264,10 @@ namespace libtorrent
int prev_size = m_downloads[download_state].size(); int prev_size = m_downloads[download_state].size();
#endif #endif
int total_downloading_pieces = 0; // since we're removing a downloading_piece, we also need to free its
for (int k = 0; k < piece_pos::num_download_categories; ++k) total_downloading_pieces += m_downloads[k].size(); // blocks that are allocated from the m_block_info array.
m_free_block_infos.push_back(i->info_idx);
std::vector<downloading_piece>::iterator other;
bool found = false;
for (int k = 0; k < piece_pos::num_download_categories; ++k)
{
other = std::find_if(
m_downloads[k].begin(), m_downloads[k].end()
, boost::bind(&downloading_piece::info, _1)
== &m_block_info[(total_downloading_pieces - 1) * m_blocks_per_piece]);
if (other != m_downloads[k].end())
{
found = true;
break;
}
}
TORRENT_ASSERT(found);
if (found && i->index != other->index)
{
std::copy(other->info, other->info + m_blocks_per_piece, i->info);
other->info = i->info;
}
m_piece_map[i->index].download_state = piece_pos::piece_open; m_piece_map[i->index].download_state = piece_pos::piece_open;
m_downloads[download_state].erase(i); m_downloads[download_state].erase(i);
@ -330,6 +307,20 @@ namespace libtorrent
*zero_prio = m_downloads[piece_pos::piece_zero_prio].size(); *zero_prio = m_downloads[piece_pos::piece_zero_prio].size();
} }
piece_picker::block_info* piece_picker::blocks_for_piece(
downloading_piece const& dp)
{
int idx = int(dp.info_idx) * m_blocks_per_piece;
TORRENT_ASSERT(idx + m_blocks_per_piece <= m_block_info.size());
return &m_block_info[idx];
}
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);
}
#if TORRENT_USE_INVARIANT_CHECKS #if TORRENT_USE_INVARIANT_CHECKS
void piece_picker::check_piece_state() const void piece_picker::check_piece_state() const
@ -346,16 +337,17 @@ namespace libtorrent
downloading_piece const& next = *(i + 1); downloading_piece const& next = *(i + 1);
// TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing); // TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing);
TORRENT_ASSERT(dp.index < next.index); TORRENT_ASSERT(dp.index < next.index);
TORRENT_ASSERT(dp.info >= &m_block_info[0]); TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece
TORRENT_ASSERT(dp.info < &m_block_info[0] + m_block_info.size()); + m_blocks_per_piece <= m_block_info.size());
TORRENT_ASSERT((dp.info - &m_block_info[0]) % m_blocks_per_piece == 0); block_info const* info = blocks_for_piece(dp);
for (int k = 0; k < m_blocks_per_piece; ++k) for (int k = 0; k < m_blocks_per_piece; ++k)
{ {
if (dp.info[k].peer) if (info[k].peer)
{ {
torrent_peer* p = (torrent_peer*)dp.info[k].peer; torrent_peer* p = (torrent_peer*)info[k].peer;
TORRENT_ASSERT(p->in_use); TORRENT_ASSERT(p->in_use);
TORRENT_ASSERT(p->connection == NULL || static_cast<peer_connection*>(p->connection)->m_in_use); TORRENT_ASSERT(p->connection == NULL
|| static_cast<peer_connection*>(p->connection)->m_in_use);
} }
} }
} }
@ -475,19 +467,17 @@ namespace libtorrent
downloading_piece const& next = *(i + 1); downloading_piece const& next = *(i + 1);
// TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing); // TORRENT_ASSERT(dp.finished + dp.writing >= next.finished + next.writing);
TORRENT_ASSERT(dp.index < next.index); TORRENT_ASSERT(dp.index < next.index);
TORRENT_ASSERT(dp.info >= &m_block_info[0]); TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece
TORRENT_ASSERT(dp.info < &m_block_info[0] + m_block_info.size()); + m_blocks_per_piece <= m_block_info.size());
TORRENT_ASSERT((dp.info - &m_block_info[0]) % m_blocks_per_piece == 0);
#if TORRENT_USE_ASSERTS #if TORRENT_USE_ASSERTS
block_info const* info = blocks_for_piece(dp);
for (int k = 0; k < m_blocks_per_piece; ++k) for (int k = 0; k < m_blocks_per_piece; ++k)
{ {
if (dp.info[k].peer) if (!info[k].peer) continue;
{ torrent_peer* p = (torrent_peer*)info[k].peer;
torrent_peer* p = (torrent_peer*)dp.info[k].peer; TORRENT_ASSERT(p->in_use);
TORRENT_ASSERT(p->in_use); TORRENT_ASSERT(p->connection == NULL
TORRENT_ASSERT(p->connection == NULL || static_cast<peer_connection*>(p->connection)->m_in_use);
|| static_cast<peer_connection*>(p->connection)->m_in_use);
}
} }
#endif #endif
} }
@ -509,32 +499,33 @@ namespace libtorrent
int num_finished = 0; int num_finished = 0;
int num_writing = 0; int num_writing = 0;
int num_open = 0; int num_open = 0;
block_info const* info = blocks_for_piece(*i);
for (int k = 0; k < num_blocks; ++k) for (int k = 0; k < num_blocks; ++k)
{ {
TORRENT_ASSERT(i->info[k].piece_index == i->index); TORRENT_ASSERT(info[k].piece_index == i->index);
TORRENT_ASSERT(i->info[k].peer == 0 TORRENT_ASSERT(info[k].peer == 0
|| static_cast<torrent_peer*>(i->info[k].peer)->in_use); || static_cast<torrent_peer*>(info[k].peer)->in_use);
if (i->info[k].state == block_info::state_finished) if (info[k].state == block_info::state_finished)
{ {
++num_finished; ++num_finished;
TORRENT_ASSERT(i->info[k].num_peers == 0); TORRENT_ASSERT(info[k].num_peers == 0);
} }
else if (i->info[k].state == block_info::state_requested) else if (info[k].state == block_info::state_requested)
{ {
++num_requested; ++num_requested;
blocks_requested = true; blocks_requested = true;
TORRENT_ASSERT(i->info[k].num_peers > 0); TORRENT_ASSERT(info[k].num_peers > 0);
} }
else if (i->info[k].state == block_info::state_writing) else if (info[k].state == block_info::state_writing)
{ {
++num_writing; ++num_writing;
TORRENT_ASSERT(i->info[k].num_peers == 0); TORRENT_ASSERT(info[k].num_peers == 0);
} }
else if (i->info[k].state == block_info::state_none) else if (info[k].state == block_info::state_none)
{ {
++num_open; ++num_open;
TORRENT_ASSERT(i->info[k].num_peers == 0); TORRENT_ASSERT(info[k].num_peers == 0);
} }
} }
@ -1111,8 +1102,8 @@ namespace libtorrent
std::vector<downloading_piece>::iterator i = find_dl_piece(download_state, index); std::vector<downloading_piece>::iterator i = find_dl_piece(download_state, index);
TORRENT_ASSERT(i != m_downloads[download_state].end()); TORRENT_ASSERT(i != m_downloads[download_state].end());
TORRENT_ASSERT(i->info >= &m_block_info[0] TORRENT_ASSERT(int(i->info_idx) * m_blocks_per_piece
&& i->info < &m_block_info[0] + m_block_info.size()); + m_blocks_per_piece <= m_block_info.size());
i->locked = false; i->locked = false;
@ -2408,10 +2399,12 @@ get_out:
// as backups // as backups
int num_blocks_in_piece = blocks_in_piece(dp->index); int num_blocks_in_piece = blocks_in_piece(dp->index);
TORRENT_ASSERT(dp->requested > 0); TORRENT_ASSERT(dp->requested > 0);
block_info const* binfo = blocks_for_piece(*dp);
for (int j = 0; j < num_blocks_in_piece; ++j) for (int j = 0; j < num_blocks_in_piece; ++j)
{ {
block_info const& info = dp->info[j]; block_info const& info = binfo[j];
TORRENT_ASSERT(info.peer == 0 || static_cast<torrent_peer*>(info.peer)->in_use); TORRENT_ASSERT(info.peer == 0
|| static_cast<torrent_peer*>(info.peer)->in_use);
TORRENT_ASSERT(info.piece_index == dp->index); TORRENT_ASSERT(info.piece_index == dp->index);
if (info.state != block_info::state_requested if (info.state != block_info::state_requested
|| info.peer == peer) || info.peer == peer)
@ -2449,9 +2442,10 @@ get_out:
continue; continue;
int num_blocks_in_piece = blocks_in_piece(i->index); 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) for (int j = 0; j < num_blocks_in_piece; ++j)
{ {
block_info const& info = i->info[j]; block_info const& info = binfo[j];
TORRENT_ASSERT(info.piece_index == i->index); TORRENT_ASSERT(info.piece_index == i->index);
if (info.state != block_info::state_none) continue; if (info.state != block_info::state_none) continue;
std::vector<piece_block>::iterator k = std::find( std::vector<piece_block>::iterator k = std::find(
@ -2468,10 +2462,11 @@ get_out:
= m_downloads[piece_pos::piece_downloading].begin() = m_downloads[piece_pos::piece_downloading].begin()
, end(m_downloads[piece_pos::piece_downloading].end()); l != end; ++l) , end(m_downloads[piece_pos::piece_downloading].end()); l != end; ++l)
{ {
block_info const* binfo2 = blocks_for_piece(*l);
fprintf(stderr, "%d : ", l->index); fprintf(stderr, "%d : ", l->index);
int num_blocks_in_piece = blocks_in_piece(l->index); int num_blocks_in_piece = blocks_in_piece(l->index);
for (int m = 0; m < num_blocks_in_piece; ++m) for (int m = 0; m < num_blocks_in_piece; ++m)
fprintf(stderr, "%d", l->info[m].state); fprintf(stderr, "%d", binfo2[m].state);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
@ -2499,9 +2494,10 @@ get_out:
// this assert is not valid for web_seeds // this assert is not valid for web_seeds
/* /*
int num_blocks_in_piece = blocks_in_piece(k->index); int num_blocks_in_piece = blocks_in_piece(k->index);
block_info const* binfo = blocks_for_piece(*k);
for (int j = 0; j < num_blocks_in_piece; ++j) for (int j = 0; j < num_blocks_in_piece; ++j)
{ {
block_info const& info = k->info[j]; block_info const& info = binfo[j];
TORRENT_ASSERT(info.piece_index == k->index); TORRENT_ASSERT(info.piece_index == k->index);
if (info.state == block_info::state_finished) continue; if (info.state == block_info::state_finished) continue;
TORRENT_ASSERT(info.peer != 0); TORRENT_ASSERT(info.peer != 0);
@ -2572,58 +2568,57 @@ get_out:
} }
} }
namespace // the first bool is true if this is the only peer that has requested and downloaded
// blocks from this piece.
// the second bool is true if this is the only active peer that is requesting
// and downloading blocks from this piece. Active means having a connection.
// TODO: 2 the first_block returned here is the largest free range, not
// the first-fit range, which would be better
boost::tuple<bool, bool, int, int> piece_picker::requested_from(
piece_picker::downloading_piece const& p
, int num_blocks_in_piece, void* peer) const
{ {
// the first bool is true if this is the only peer that has requested and downloaded bool exclusive = true;
// blocks from this piece. bool exclusive_active = true;
// the second bool is true if this is the only active peer that is requesting int contiguous_blocks = 0;
// and downloading blocks from this piece. Active means having a connection. int max_contiguous = 0;
// TODO: 2 the first_block returned here is the largest free range, not int first_block = 0;
// the first-fit range, which would be better block_info const* binfo = blocks_for_piece(p);
boost::tuple<bool, bool, int, int> requested_from( for (int j = 0; j < num_blocks_in_piece; ++j)
piece_picker::downloading_piece const& p
, int num_blocks_in_piece, void* peer)
{ {
bool exclusive = true; piece_picker::block_info const& info = binfo[j];
bool exclusive_active = true; TORRENT_ASSERT(info.peer == 0 || static_cast<torrent_peer*>(info.peer)->in_use);
int contiguous_blocks = 0; TORRENT_ASSERT(info.piece_index == p.index);
int max_contiguous = 0; if (info.state == piece_picker::block_info::state_none)
int first_block = 0;
for (int j = 0; j < num_blocks_in_piece; ++j)
{ {
piece_picker::block_info const& info = p.info[j]; ++contiguous_blocks;
TORRENT_ASSERT(info.peer == 0 || static_cast<torrent_peer*>(info.peer)->in_use); continue;
TORRENT_ASSERT(info.piece_index == p.index);
if (info.state == piece_picker::block_info::state_none)
{
++contiguous_blocks;
continue;
}
if (contiguous_blocks > max_contiguous)
{
max_contiguous = contiguous_blocks;
first_block = j - contiguous_blocks;
}
contiguous_blocks = 0;
if (info.peer != peer)
{
exclusive = false;
if (info.state == piece_picker::block_info::state_requested
&& info.peer != 0)
{
exclusive_active = false;
}
}
} }
if (contiguous_blocks > max_contiguous) if (contiguous_blocks > max_contiguous)
{ {
max_contiguous = contiguous_blocks; max_contiguous = contiguous_blocks;
first_block = num_blocks_in_piece - contiguous_blocks; first_block = j - contiguous_blocks;
}
contiguous_blocks = 0;
if (info.peer != peer)
{
exclusive = false;
if (info.state == piece_picker::block_info::state_requested
&& info.peer != 0)
{
exclusive_active = false;
}
} }
return boost::make_tuple(exclusive, exclusive_active, max_contiguous
, first_block);
} }
if (contiguous_blocks > max_contiguous)
{
max_contiguous = contiguous_blocks;
first_block = num_blocks_in_piece - contiguous_blocks;
}
return boost::make_tuple(exclusive, exclusive_active, max_contiguous
, first_block);
} }
int piece_picker::add_blocks(int piece int piece_picker::add_blocks(int piece
, bitfield const& pieces , bitfield const& pieces
@ -2742,6 +2737,8 @@ get_out:
// pieces that only they have downloaded/requested from // pieces that only they have downloaded/requested from
if ((options & on_parole) && !exclusive) return num_blocks; if ((options & on_parole) && !exclusive) return num_blocks;
block_info const* binfo = blocks_for_piece(dp);
// we prefer whole blocks, but there are other peers // we prefer whole blocks, but there are other peers
// downloading from this piece and there aren't enough contiguous blocks // downloading from this piece and there aren't enough contiguous blocks
// to pick, add it as backups. // to pick, add it as backups.
@ -2758,7 +2755,7 @@ get_out:
{ {
// ignore completed blocks and already requested blocks // ignore completed blocks and already requested blocks
int block_idx = (j + first_block) % num_blocks_in_piece; int block_idx = (j + first_block) % num_blocks_in_piece;
block_info const& info = dp.info[block_idx]; block_info const& info = binfo[block_idx];
TORRENT_ASSERT(info.piece_index == dp.index); TORRENT_ASSERT(info.piece_index == dp.index);
if (info.state != block_info::state_none) continue; if (info.state != block_info::state_none) continue;
backup_blocks2.push_back(piece_block(dp.index, block_idx)); backup_blocks2.push_back(piece_block(dp.index, block_idx));
@ -2770,7 +2767,7 @@ get_out:
{ {
// ignore completed blocks and already requested blocks // ignore completed blocks and already requested blocks
int block_idx = (j + first_block) % num_blocks_in_piece; int block_idx = (j + first_block) % num_blocks_in_piece;
block_info const& info = dp.info[block_idx]; block_info const& info = binfo[block_idx];
TORRENT_ASSERT(info.piece_index == dp.index); TORRENT_ASSERT(info.piece_index == dp.index);
if (info.state != block_info::state_none) continue; if (info.state != block_info::state_none) continue;
@ -2869,11 +2866,12 @@ get_out:
TORRENT_ASSERT(int(i->finished) + int(i->writing) == max_blocks); TORRENT_ASSERT(int(i->finished) + int(i->writing) == max_blocks);
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS #if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
block_info const* info = blocks_for_piece(*i);
for (int k = 0; k < max_blocks; ++k) for (int k = 0; k < max_blocks; ++k)
{ {
TORRENT_ASSERT(i->info[k].piece_index == index); TORRENT_ASSERT(info[k].piece_index == index);
TORRENT_ASSERT(i->info[k].state == block_info::state_finished TORRENT_ASSERT(info[k].state == block_info::state_finished
|| i->info[k].state == block_info::state_writing); || info[k].state == block_info::state_writing);
} }
#endif #endif
@ -3020,8 +3018,10 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(i->info[block.block_index].piece_index == block.piece_index);
return i->info[block.block_index].state; block_info const* info = blocks_for_piece(*i);
TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return info[block.block_index].state;
} }
bool piece_picker::is_requested(piece_block block) const bool piece_picker::is_requested(piece_block block) const
@ -3039,10 +3039,10 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(i->info >= &m_block_info[0]
&& i->info < &m_block_info[0] + m_block_info.size()); block_info const* info = blocks_for_piece(*i);
TORRENT_ASSERT(i->info[block.block_index].piece_index == block.piece_index); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return i->info[block.block_index].state == block_info::state_requested; return info[block.block_index].state == block_info::state_requested;
} }
bool piece_picker::is_downloaded(piece_block block) const bool piece_picker::is_downloaded(piece_block block) const
@ -3060,11 +3060,11 @@ get_out:
std::vector<downloading_piece>::const_iterator i = find_dl_piece(state std::vector<downloading_piece>::const_iterator i = find_dl_piece(state
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(i->info >= &m_block_info[0]
&& i->info < &m_block_info[0] + m_block_info.size()); block_info const* info = blocks_for_piece(*i);
TORRENT_ASSERT(i->info[block.block_index].piece_index == block.piece_index); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return i->info[block.block_index].state == block_info::state_finished return info[block.block_index].state == block_info::state_finished
|| i->info[block.block_index].state == block_info::state_writing; || info[block.block_index].state == block_info::state_writing;
} }
bool piece_picker::is_finished(piece_block block) const bool piece_picker::is_finished(piece_block block) const
@ -3082,10 +3082,10 @@ get_out:
std::vector<downloading_piece>::const_iterator i = find_dl_piece(p.download_queue() std::vector<downloading_piece>::const_iterator i = find_dl_piece(p.download_queue()
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
TORRENT_ASSERT(i->info >= &m_block_info[0]
&& i->info < &m_block_info[0] + m_block_info.size()); block_info const* info = blocks_for_piece(*i);
TORRENT_ASSERT(i->info[block.block_index].piece_index == block.piece_index); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index);
return i->info[block.block_index].state == block_info::state_finished; return info[block.block_index].state == block_info::state_finished;
} }
// options may be 0 or piece_picker::reverse // options may be 0 or piece_picker::reverse
@ -3121,7 +3121,8 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index); if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index); dlpiece_iter dp = add_download_piece(block.piece_index);
block_info& info = dp->info[block.block_index]; block_info* binfo = blocks_for_piece(*dp);
block_info& info = binfo[block.block_index];
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
info.state = block_info::state_requested; info.state = block_info::state_requested;
info.peer = peer; info.peer = peer;
@ -3144,9 +3145,8 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue() std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info& info = i->info[block.block_index]; block_info* binfo = blocks_for_piece(*i);
TORRENT_ASSERT(&info >= &m_block_info[0]); block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
if (info.state == block_info::state_writing if (info.state == block_info::state_writing
|| info.state == block_info::state_finished) || info.state == block_info::state_finished)
@ -3208,7 +3208,8 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info const& info = i->info[block.block_index]; block_info 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]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
@ -3270,7 +3271,8 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index); if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index); dlpiece_iter dp = add_download_piece(block.piece_index);
block_info& info = dp->info[block.block_index]; block_info* binfo = 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]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
@ -3289,7 +3291,8 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue() std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info& info = i->info[block.block_index]; block_info* binfo = 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]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3376,7 +3379,8 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(state, block.piece_index); std::vector<downloading_piece>::iterator i = find_dl_piece(state, block.piece_index);
if (i == m_downloads[state].end()) return; if (i == m_downloads[state].end()) return;
block_info& info = i->info[block.block_index]; block_info* binfo = 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]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
@ -3447,7 +3451,8 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info& info = i->info[block.block_index]; block_info* binfo = blocks_for_piece(*i);
block_info& info = binfo[block.block_index];
if (info.state == block_info::state_finished) return; if (info.state == block_info::state_finished) return;
@ -3521,7 +3526,8 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index); if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index); dlpiece_iter dp = add_download_piece(block.piece_index);
block_info& info = dp->info[block.block_index]; block_info* binfo = 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]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
@ -3542,9 +3548,8 @@ get_out:
std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue() std::vector<downloading_piece>::iterator i = find_dl_piece(p.download_queue()
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end());
block_info& info = i->info[block.block_index]; block_info* binfo = blocks_for_piece(*i);
TORRENT_ASSERT(&info >= &m_block_info[0]); block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);
if (info.state == block_info::state_finished) return; if (info.state == block_info::state_finished) return;
@ -3625,12 +3630,12 @@ get_out:
std::vector<downloading_piece>::const_iterator i std::vector<downloading_piece>::const_iterator i
= find_dl_piece(state, index); = find_dl_piece(state, index);
TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i != m_downloads[state].end());
TORRENT_ASSERT(i->info >= &m_block_info[0] block_info const* binfo = blocks_for_piece(*i);
&& i->info < &m_block_info[0] + m_block_info.size());
for (int j = 0; j != num_blocks; ++j) for (int j = 0; j != num_blocks; ++j)
{ {
TORRENT_ASSERT(i->info[j].peer == 0 || static_cast<torrent_peer*>(i->info[j].peer)->in_use); TORRENT_ASSERT(binfo[j].peer == 0
d.push_back(i->info[j].peer); || static_cast<torrent_peer*>(binfo[j].peer)->in_use);
d.push_back(binfo[j].peer);
} }
} }
@ -3643,11 +3648,12 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(block.block_index != piece_block::invalid.block_index); TORRENT_ASSERT(block.block_index != piece_block::invalid.block_index);
TORRENT_ASSERT(i->info[block.block_index].piece_index == block.piece_index); block_info const* binfo = blocks_for_piece(*i);
if (i->info[block.block_index].state == block_info::state_none) TORRENT_ASSERT(binfo[block.block_index].piece_index == block.piece_index);
if (binfo[block.block_index].state == block_info::state_none)
return 0; return 0;
void* peer = i->info[block.block_index].peer; void* peer = binfo[block.block_index].peer;
TORRENT_ASSERT(peer == 0 || static_cast<torrent_peer*>(peer)->in_use); TORRENT_ASSERT(peer == 0 || static_cast<torrent_peer*>(peer)->in_use);
return peer; return peer;
} }
@ -3677,9 +3683,8 @@ get_out:
, block.piece_index); , block.piece_index);
TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(i != m_downloads[state].end());
block_info& info = i->info[block.block_index]; block_info* binfo = blocks_for_piece(*i);
TORRENT_ASSERT(&info >= &m_block_info[0]); block_info& info = binfo[block.block_index];
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
TORRENT_ASSERT(info.peer == 0 || static_cast<torrent_peer*>(info.peer)->in_use); TORRENT_ASSERT(info.peer == 0 || static_cast<torrent_peer*>(info.peer)->in_use);
TORRENT_ASSERT(info.piece_index == block.piece_index); TORRENT_ASSERT(info.piece_index == block.piece_index);

View File

@ -3739,19 +3739,20 @@ namespace libtorrent
} }
#endif #endif
piece_picker::block_info* info = m_picker->blocks_for_piece(*i);
for (int j = 0; j < blocks_per_piece; ++j) for (int j = 0; j < blocks_per_piece; ++j)
{ {
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j))
== (i->info[j].state == piece_picker::block_info::state_finished)); == (info[j].state == piece_picker::block_info::state_finished));
#endif #endif
if (i->info[j].state == piece_picker::block_info::state_finished) if (info[j].state == piece_picker::block_info::state_finished)
{ {
corr += block_bytes_wanted(piece_block(index, j)); corr += block_bytes_wanted(piece_block(index, j));
} }
TORRENT_ASSERT(corr >= 0); TORRENT_ASSERT(corr >= 0);
TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece() TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece()
|| i->info[j].state != piece_picker::block_info::state_finished); || info[j].state != piece_picker::block_info::state_finished);
} }
st.total_done += corr; st.total_done += corr;
@ -3820,9 +3821,11 @@ namespace libtorrent
dl_queue.begin(); i != dl_queue.end(); ++i) dl_queue.begin(); i != dl_queue.end(); ++i)
{ {
fprintf(stderr, " %d ", i->index); fprintf(stderr, " %d ", i->index);
piece_picker::block_info* info = m_picker->blocks_for_piece(*i);
for (int j = 0; j < blocks_per_piece; ++j) for (int j = 0; j < blocks_per_piece; ++j)
{ {
char const* state = i->info[j].state == piece_picker::block_info::state_finished ? "1" : "0"; char const* state = info[j].state
== piece_picker::block_info::state_finished ? "1" : "0";
fputs(state, stderr); fputs(state, stderr);
} }
fputs("\n", stderr); fputs("\n", stderr);
@ -6846,12 +6849,13 @@ namespace libtorrent
const int num_bitmask_bytes const int num_bitmask_bytes
= (std::max)(num_blocks_per_piece / 8, 1); = (std::max)(num_blocks_per_piece / 8, 1);
piece_picker::block_info const* info = m_picker->blocks_for_piece(*i);
for (int j = 0; j < num_bitmask_bytes; ++j) for (int j = 0; j < num_bitmask_bytes; ++j)
{ {
unsigned char v = 0; unsigned char v = 0;
int bits = (std::min)(num_blocks_per_piece - j*8, 8); int bits = (std::min)(num_blocks_per_piece - j*8, 8);
for (int k = 0; k < bits; ++k) for (int k = 0; k < bits; ++k)
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished) v |= (info[j*8+k].state == piece_picker::block_info::state_finished)
? (1 << k) : 0; ? (1 << k) : 0;
bitmask.append(1, v); bitmask.append(1, v);
TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1); TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1);
@ -7126,7 +7130,7 @@ namespace libtorrent
} }
} }
void torrent::get_download_queue(std::vector<partial_piece_info>* queue) void torrent::get_download_queue(std::vector<partial_piece_info>* queue) const
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
queue->clear(); queue->clear();
@ -7159,22 +7163,23 @@ namespace libtorrent
TORRENT_ASSERT(counter * blocks_per_piece + pi.blocks_in_piece <= int(blk.size())); TORRENT_ASSERT(counter * blocks_per_piece + pi.blocks_in_piece <= int(blk.size()));
pi.blocks = &blk[counter * blocks_per_piece]; pi.blocks = &blk[counter * blocks_per_piece];
int piece_size = int(torrent_file().piece_size(i->index)); int piece_size = int(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) for (int j = 0; j < pi.blocks_in_piece; ++j)
{ {
block_info& bi = pi.blocks[j]; block_info& bi = pi.blocks[j];
bi.state = i->info[j].state; bi.state = info[j].state;
bi.block_size = j < pi.blocks_in_piece - 1 ? block_size() bi.block_size = j < pi.blocks_in_piece - 1 ? block_size()
: piece_size - (j * block_size()); : piece_size - (j * block_size());
bool complete = bi.state == block_info::writing bool complete = bi.state == block_info::writing
|| bi.state == block_info::finished; || bi.state == block_info::finished;
if (i->info[j].peer == 0) if (info[j].peer == 0)
{ {
bi.set_peer(tcp::endpoint()); bi.set_peer(tcp::endpoint());
bi.bytes_progress = complete ? bi.block_size : 0; bi.bytes_progress = complete ? bi.block_size : 0;
} }
else else
{ {
torrent_peer* p = static_cast<torrent_peer*>(i->info[j].peer); torrent_peer* p = static_cast<torrent_peer*>(info[j].peer);
TORRENT_ASSERT(p->in_use); TORRENT_ASSERT(p->in_use);
if (p->connection) if (p->connection)
{ {
@ -7207,7 +7212,7 @@ namespace libtorrent
} }
} }
pi.blocks[j].num_peers = i->info[j].num_peers; pi.blocks[j].num_peers = info[j].num_peers;
} }
pi.piece_index = i->index; pi.piece_index = i->index;
queue->push_back(pi); queue->push_back(pi);
@ -10134,7 +10139,9 @@ namespace libtorrent
bool operator<(busy_block_t rhs) const { return peers < rhs.peers; } bool operator<(busy_block_t rhs) const { return peers < rhs.peers; }
}; };
void pick_busy_blocks(int piece, int blocks_in_piece void pick_busy_blocks(piece_picker const* picker
, int piece
, int blocks_in_piece
, int timed_out , int timed_out
, std::vector<piece_block>& interesting_blocks , std::vector<piece_block>& interesting_blocks
, piece_picker::downloading_piece const& pi) , piece_picker::downloading_piece const& pi)
@ -10149,27 +10156,29 @@ namespace libtorrent
= TORRENT_ALLOCA(busy_block_t, blocks_in_piece); = TORRENT_ALLOCA(busy_block_t, blocks_in_piece);
int busy_count = 0; int busy_count = 0;
piece_picker::block_info const* info = picker->blocks_for_piece(pi);
// pick busy blocks from the piece // pick busy blocks from the piece
for (int k = 0; k < blocks_in_piece; ++k) for (int k = 0; k < blocks_in_piece; ++k)
{ {
// only consider blocks that have been requested // only consider blocks that have been requested
// and we're still waiting for them // and we're still waiting for them
if (pi.info[k].state != piece_picker::block_info::state_requested) if (info[k].state != piece_picker::block_info::state_requested)
continue; continue;
piece_block b(piece, k); piece_block b(piece, k);
// only allow a single additional request per block, in order // only allow a single additional request per block, in order
// to spread it out evenly across all stalled blocks // to spread it out evenly across all stalled blocks
if (pi.info[k].num_peers > timed_out) if (info[k].num_peers > timed_out)
continue; continue;
busy_blocks[busy_count].peers = pi.info[k].num_peers; busy_blocks[busy_count].peers = info[k].num_peers;
busy_blocks[busy_count].index = k; busy_blocks[busy_count].index = k;
++busy_count; ++busy_count;
#if TORRENT_DEBUG_STREAMING > 1 #if TORRENT_DEBUG_STREAMING > 1
printf(" [%d (%d)]", b.block_index, pi.info[k].num_peers); printf(" [%d (%d)]", b.block_index, info[k].num_peers);
#endif #endif
} }
#if TORRENT_DEBUG_STREAMING > 1 #if TORRENT_DEBUG_STREAMING > 1
@ -10194,7 +10203,7 @@ namespace libtorrent
, std::set<peer_connection*>& peers_with_requests , std::set<peer_connection*>& peers_with_requests
, piece_picker::downloading_piece const& pi , piece_picker::downloading_piece const& pi
, time_critical_piece* i , time_critical_piece* i
, piece_picker* picker , piece_picker const* picker
, int blocks_in_piece , int blocks_in_piece
, int timed_out) , int timed_out)
{ {
@ -10275,7 +10284,7 @@ namespace libtorrent
printf("pick busy blocks\n"); printf("pick busy blocks\n");
#endif #endif
pick_busy_blocks(i->piece, blocks_in_piece, timed_out pick_busy_blocks(picker, i->piece, blocks_in_piece, timed_out
, interesting_blocks, pi); , interesting_blocks, pi);
} }
@ -11045,7 +11054,7 @@ namespace libtorrent
boost::int64_t offset = boost::int64_t(i->index) * m_torrent_file->piece_length(); boost::int64_t offset = boost::int64_t(i->index) * m_torrent_file->piece_length();
int file = fs.file_index_at_offset(offset); int file = fs.file_index_at_offset(offset);
int num_blocks = m_picker->blocks_in_piece(i->index); int num_blocks = m_picker->blocks_in_piece(i->index);
piece_picker::block_info const* info = i->info; piece_picker::block_info const* info = m_picker->blocks_for_piece(*i);
for (int k = 0; k < num_blocks; ++k) for (int k = 0; k < num_blocks; ++k)
{ {
TORRENT_ASSERT(file < fs.num_files()); TORRENT_ASSERT(file < fs.num_files());