remove speed affinity feature in piece-picker and peers

This commit is contained in:
Arvid Norberg 2015-02-08 21:17:00 +00:00
parent 497f7a4a27
commit 9fb98b1151
8 changed files with 140 additions and 296 deletions

View File

@ -855,9 +855,11 @@ namespace libtorrent
{
// internal
block_downloading_alert(const torrent_handle& h, tcp::endpoint const& ep
, peer_id const& peer_id, char const* speedmsg, int block_num, int piece_num)
, peer_id const& peer_id, int block_num, int piece_num)
: peer_alert(h, ep, peer_id)
, peer_speedmsg(speedmsg)
#ifndef TORRENT_NO_DEPRECATE
, peer_speedmsg("")
#endif
, block_index(block_num)
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); }
@ -867,7 +869,9 @@ namespace libtorrent
const static int static_category = alert::progress_notification;
virtual std::string message() const;
#ifndef TORRENT_NO_DEPRECATE
char const* peer_speedmsg;
#endif
int block_index;
int piece_index;
};

View File

@ -325,9 +325,6 @@ namespace libtorrent
void peer_disconnected_other()
{ m_exceeded_limit = false; }
enum peer_speed_t { slow = 1, medium, fast };
peer_speed_t peer_speed();
void send_allowed_set();
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -1137,12 +1134,6 @@ namespace libtorrent
char m_country[2];
#endif
// this is a measurement of how fast the peer
// it allows some variance without changing
// back and forth between states. values are enums
// from peer_speed_t.
boost::uint8_t m_speed;
// if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks.
// where n is the value of this variable.

View File

@ -138,15 +138,6 @@ namespace libtorrent
#endif
};
// the peers that are downloading this piece
// are considered fast peers or slow peers.
// none is set if the blocks were downloaded
// in a previous session
// TODO:3 perhaps the piece_state feature could be removed. It's not
// obvious that it has any effect
enum piece_state_t
{ none, slow, medium, fast };
enum options_t
{
// pick rarest first
@ -159,24 +150,25 @@ namespace libtorrent
prioritize_partials = 8,
// pick pieces in sequential order
sequential = 16,
// have affinity to pieces with the same speed category
speed_affinity = 32,
// treat pieces with priority 6 and below as filtered
// to trigger end-game mode until all prio 7 pieces are
// completed
time_critical_mode = 64,
time_critical_mode = 32,
// only expands pieces (when prefer contiguous blocks is set)
// within properly aligned ranges, not the largest possible
// range of pieces.
align_expanded_pieces = 128
align_expanded_pieces = 64
};
struct downloading_piece
{
downloading_piece() : info(NULL), index(-1)
, finished(0), state(none), writing(0)
, passed_hash_check(0), locked(0)
, requested(0), outstanding_hash_check(0) {}
, finished(0)
, passed_hash_check(0)
, writing(0)
, locked(0)
, requested(0)
, outstanding_hash_check(0) {}
bool operator<(downloading_piece const& rhs) const { return index < rhs.index; }
@ -189,13 +181,7 @@ namespace libtorrent
int index;
// the number of blocks in the finished state
boost::uint16_t finished:14;
// the speed state of this piece
boost::uint16_t state:2;
// the number of blocks in the writing state
boost::uint16_t writing:14;
boost::uint16_t finished:15;
// set to true when the hash check job
// returns with a valid hash for this piece.
@ -205,6 +191,9 @@ namespace libtorrent
// set.
boost::uint16_t passed_hash_check:1;
// the number of blocks in the writing state
boost::uint16_t writing:15;
// when this is set, blocks from this piece may
// not be picked. This is used when the hash check
// fails or writing to the disk fails, while waiting
@ -308,7 +297,7 @@ namespace libtorrent
// (i.e. higher overhead per request).
void pick_pieces(bitfield const& pieces
, std::vector<piece_block>& interesting_blocks, int num_blocks
, int prefer_contiguous_blocks, void* peer, piece_state_t speed
, int prefer_contiguous_blocks, void* peer
, int options, std::vector<int> const& suggested_pieces
, int num_peers
, counters& pc
@ -326,7 +315,7 @@ namespace libtorrent
, std::vector<piece_block>& backup_blocks2
, int num_blocks, int prefer_contiguous_blocks
, void* peer, std::vector<int> const& ignore
, piece_state_t speed, int options) const;
, int options) const;
// picks blocks only from downloading pieces
int add_blocks_downloading(downloading_piece const& dp
@ -335,7 +324,7 @@ namespace libtorrent
, std::vector<piece_block>& backup_blocks
, std::vector<piece_block>& backup_blocks2
, int num_blocks, int prefer_contiguous_blocks
, void* peer, piece_state_t speed
, void* peer
, int options) const;
// clears the peer pointer in all downloading pieces with this
@ -361,7 +350,7 @@ namespace libtorrent
// marks this piece-block as queued for downloading
// options are flags from options_t.
bool mark_as_downloading(piece_block block, void* peer
, piece_state_t s, int options = 0);
, int options = 0);
// returns true if the block was marked as writing,
// and false if the block is already finished or writing

View File

@ -181,7 +181,6 @@ namespace libtorrent
, m_upload_rate_peak(0)
, m_send_barrier(INT_MAX)
, m_desired_queue_size(2)
, m_speed(slow)
, m_prefer_contiguous_blocks(0)
, m_disk_read_failures(0)
, m_outstanding_piece_verification(0)
@ -855,10 +854,6 @@ namespace libtorrent
// and prioritize finishing them
ret |= piece_picker::prioritize_partials;
}
else
{
ret |= piece_picker::rarest_first | piece_picker::speed_affinity;
}
if (m_snubbed)
{
@ -3308,25 +3303,6 @@ namespace libtorrent
return false;
}
piece_picker::piece_state_t state;
peer_speed_t speed = peer_speed();
char const* speedmsg = 0;
if (speed == fast)
{
speedmsg = "fast";
state = piece_picker::fast;
}
else if (speed == medium)
{
speedmsg = "medium";
state = piece_picker::medium;
}
else
{
speedmsg = "slow";
state = piece_picker::slow;
}
if ((flags & req_busy) && !(flags & req_time_critical))
{
// this block is busy (i.e. it has been requested
@ -3362,7 +3338,7 @@ namespace libtorrent
}
}
if (!t->picker().mark_as_downloading(block, peer_info_struct(), state
if (!t->picker().mark_as_downloading(block, peer_info_struct()
, picker_options()))
{
#if defined TORRENT_LOGGING
@ -3375,7 +3351,7 @@ namespace libtorrent
if (t->alerts().should_post<block_downloading_alert>())
{
t->alerts().post_alert(block_downloading_alert(t->get_handle(),
remote(), pid(), speedmsg, block.block_index, block.piece_index));
remote(), pid(), block.block_index, block.piece_index));
}
pending_block pb(block);
@ -6524,27 +6500,6 @@ namespace libtorrent
}
#endif
peer_connection::peer_speed_t peer_connection::peer_speed()
{
TORRENT_ASSERT(is_single_thread());
shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
int download_rate = int(statistics().download_payload_rate());
int torrent_download_rate = int(t->statistics().download_payload_rate());
if (download_rate > 512 && download_rate > torrent_download_rate / 16)
m_speed = fast;
else if (download_rate > 4096 && download_rate > torrent_download_rate / 64)
m_speed = medium;
else if (download_rate < torrent_download_rate / 15 && m_speed == fast)
m_speed = medium;
else
m_speed = slow;
return peer_connection::peer_speed_t(m_speed);
}
void peer_connection::keep_alive()
{
TORRENT_ASSERT(is_single_thread());

View File

@ -548,7 +548,6 @@ namespace libtorrent
break;
}
TORRENT_ASSERT(blocks_requested == (i->state != none));
TORRENT_ASSERT(num_requested == i->requested);
TORRENT_ASSERT(num_writing == i->writing);
TORRENT_ASSERT(num_finished == i->finished);
@ -1920,10 +1919,6 @@ namespace libtorrent
// peers. the void* is the pointer to the torrent_peer of the peer we're
// picking pieces from. This is used when downloading whole pieces, to only
// pick from the same piece the same peer is downloading from.
// download_state is supposed to be set to fast if the peer is downloading
// relatively fast, by some notion. Slow peers will prefer not to pick
// blocks from the same pieces as fast peers, and vice versa. Downloading
// pieces are marked as being fast, medium or slow once they're started.
// options are:
// * rarest_first
@ -1939,15 +1934,12 @@ namespace libtorrent
// peer
// * prioritize_partials
// pick blocks from downloading pieces first
// * speed_affinity
// have an affinity to pick pieces in the same speed
// category.
// only one of rarest_first or sequential can be set
void piece_picker::pick_pieces(bitfield const& pieces
, std::vector<piece_block>& interesting_blocks, int num_blocks
, int prefer_contiguous_blocks, void* peer, piece_state_t speed
, int prefer_contiguous_blocks, void* peer
, int options, std::vector<int> const& suggested_pieces
, int num_peers
, counters& pc
@ -1990,10 +1982,6 @@ namespace libtorrent
// this will be filled with blocks that we should not request
// unless we can't find num_blocks among the other ones.
// blocks that belong to pieces with a mismatching speed
// category for instance, or if we prefer whole pieces,
// blocks belonging to a piece that others have
// downloaded to
std::vector<piece_block> backup_blocks;
std::vector<piece_block> backup_blocks2;
const std::vector<int> empty_vector;
@ -2052,7 +2040,7 @@ namespace libtorrent
{
num_blocks = add_blocks_downloading(*ordered_partials[i], pieces
, interesting_blocks, backup_blocks, backup_blocks2
, num_blocks, prefer_contiguous_blocks, peer, speed, options);
, num_blocks, prefer_contiguous_blocks, peer, options);
if (num_blocks <= 0) return;
if (int(backup_blocks.size()) >= num_blocks
&& int(backup_blocks2.size()) >= num_blocks)
@ -2084,7 +2072,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, empty_vector
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
@ -2102,7 +2090,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
@ -2121,7 +2109,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
@ -2137,7 +2125,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
@ -2167,7 +2155,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
@ -2193,7 +2181,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
@ -2210,13 +2198,12 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, suggested_pieces
, speed, options);
, options);
if (num_blocks <= 0) return;
}
}
else
{
// we're not using rarest first (only for the first
// bucket, since that's where the currently downloading
// pieces are)
@ -2273,7 +2260,7 @@ namespace libtorrent
, interesting_blocks, backup_blocks
, backup_blocks2, num_blocks
, prefer_contiguous_blocks, peer, empty_vector
, speed, options);
, options);
++piece;
}
@ -2626,7 +2613,7 @@ get_out:
, std::vector<piece_block>& backup_blocks2
, int num_blocks, int prefer_contiguous_blocks
, void* peer, std::vector<int> const& ignore
, piece_state_t speed, int options) const
, int options) const
{
TORRENT_ASSERT(piece >= 0);
TORRENT_ASSERT(piece < (int)m_piece_map.size());
@ -2658,7 +2645,7 @@ get_out:
return add_blocks_downloading(*i, pieces
, interesting_blocks, backup_blocks, backup_blocks2
, num_blocks, prefer_contiguous_blocks, peer, speed, options);
, num_blocks, prefer_contiguous_blocks, peer, options);
}
int num_blocks_in_piece = blocks_in_piece(piece);
@ -2705,7 +2692,7 @@ get_out:
, std::vector<piece_block>& backup_blocks
, std::vector<piece_block>& backup_blocks2
, int num_blocks, int prefer_contiguous_blocks
, void* peer, piece_state_t speed, int options) const
, void* peer, int options) const
{
if (!pieces[dp.index]) return num_blocks;
TORRENT_ASSERT(!m_piece_map[dp.index].filtered());
@ -2768,30 +2755,6 @@ get_out:
TORRENT_ASSERT(info.piece_index == dp.index);
if (info.state != block_info::state_none) continue;
// if the piece is fast and the peer is slow, or vice versa,
// add the block as a backup.
// override this behavior if all the other blocks
// have been requested from the same peer or
// if the state of the piece is none (the
// piece will in that case change state).
if (dp.state != none && dp.state != speed
&& !exclusive_active && (options & speed_affinity))
{
if (abs(dp.state - speed) == 1)
{
// don't pick too many back-up blocks
if (int(backup_blocks.size()) >= num_blocks) return num_blocks;
backup_blocks.push_back(piece_block(dp.index, block_idx));
}
else
{
// don't pick too many back-up blocks
if (int(backup_blocks2.size()) >= num_blocks) return num_blocks;
backup_blocks2.push_back(piece_block(dp.index, block_idx));
}
continue;
}
// this block is interesting (we don't have it yet).
interesting_blocks.push_back(piece_block(dp.index, block_idx));
// we have found a block that's free to download
@ -3108,7 +3071,7 @@ get_out:
// options may be 0 or piece_picker::reverse
bool piece_picker::mark_as_downloading(piece_block block
, void* peer, piece_state_t state, int options)
, void* peer, int options)
{
#ifdef TORRENT_PICKER_LOG
std::cerr << "[" << this << "] " << "mark_as_downloading( {"
@ -3116,7 +3079,6 @@ get_out:
#endif
TORRENT_ASSERT(peer == 0 || static_cast<torrent_peer*>(peer)->in_use);
TORRENT_ASSERT(state != piece_picker::none);
TORRENT_ASSERT(block.block_index != piece_block::invalid.block_index);
TORRENT_ASSERT(block.piece_index != piece_block::invalid.piece_index);
TORRENT_ASSERT(block.piece_index < m_piece_map.size());
@ -3140,7 +3102,6 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index);
dp->state = state;
block_info& info = dp->info[block.block_index];
TORRENT_ASSERT(info.piece_index == block.piece_index);
info.state = block_info::state_requested;
@ -3210,7 +3171,6 @@ get_out:
TORRENT_ASSERT(info.peers.count(peer) == 0);
info.peers.insert(peer);
#endif
if (i->state == none) i->state = state;
}
return true;
}
@ -3291,7 +3251,6 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index);
dp->state = none;
block_info& info = dp->info[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3335,12 +3294,6 @@ get_out:
info.peers.clear();
#endif
if (i->requested == 0)
{
// there are no blocks requested in this piece.
// remove the fast/slow state from it
i->state = none;
}
update_piece_state(i);
}
return true;
@ -3529,7 +3482,6 @@ get_out:
if (prio >= 0 && !m_dirty) update(prio, p.index);
dlpiece_iter dp = add_download_piece(block.piece_index);
dp->state = none;
block_info& info = dp->info[block.block_index];
TORRENT_ASSERT(&info >= &m_block_info[0]);
TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size());
@ -3749,12 +3701,6 @@ get_out:
}
return;
}
else if (i->requested == 0)
{
// there are no blocks requested in this piece.
// remove the fast/slow state from it
i->state = none;
}
i = update_piece_state(i);
}

View File

@ -149,12 +149,6 @@ namespace libtorrent
bits = &fast_mask;
}
piece_picker::piece_state_t state;
peer_connection::peer_speed_t speed = c.peer_speed();
if (speed == peer_connection::fast) state = piece_picker::fast;
else if (speed == peer_connection::medium) state = piece_picker::medium;
else state = piece_picker::slow;
// picks the interesting pieces from this peer
// the integer is the number of pieces that
// should be guaranteed to be available for download
@ -165,7 +159,7 @@ namespace libtorrent
// then use this mode.
p.pick_pieces(*bits, interesting_pieces
, num_requests, prefer_contiguous_blocks, c.peer_info_struct()
, state, c.picker_options(), suggested, t.num_peers()
, c.picker_options(), suggested, t.num_peers()
, ses.stats_counters());
#ifdef TORRENT_LOGGING

View File

@ -1305,7 +1305,7 @@ namespace libtorrent
, boost::bind(&torrent::on_disk_write_complete
, shared_from_this(), _1, p));
piece_block block(piece, i);
picker().mark_as_downloading(block, 0, piece_picker::fast);
picker().mark_as_downloading(block, 0);
picker().mark_as_writing(block, 0);
}
verify_piece(piece);
@ -4441,7 +4441,6 @@ namespace libtorrent
if (k->timed_out || k->not_wanted) continue;
if (int(k->block.piece_index) != j->piece) continue;
m_picker->mark_as_downloading(k->block, p->peer_info_struct()
, (piece_picker::piece_state_t)p->peer_speed()
, p->picker_options());
}
for (std::vector<pending_block>::const_iterator k = rq.begin()
@ -4449,7 +4448,6 @@ namespace libtorrent
{
if (int(k->block.piece_index) != j->piece) continue;
m_picker->mark_as_downloading(k->block, p->peer_info_struct()
, (piece_picker::piece_state_t)p->peer_speed()
, p->picker_options());
}
}
@ -7154,7 +7152,6 @@ namespace libtorrent
= q.begin(); i != q.end(); ++i, ++counter)
{
partial_piece_info pi;
pi.piece_state = (partial_piece_info::state_t)i->state;
pi.blocks_in_piece = p.blocks_in_piece(i->index);
pi.finished = (int)i->finished;
pi.writing = (int)i->writing;
@ -10248,7 +10245,7 @@ namespace libtorrent
// the backup lists
picker->add_blocks(i->piece, c.get_bitfield(), interesting_blocks
, backup1, backup2, blocks_in_piece, 0, c.peer_info_struct()
, ignore, piece_picker::none, 0);
, ignore, 0);
interesting_blocks.insert(interesting_blocks.end()
, backup1.begin(), backup1.end());

View File

@ -124,14 +124,14 @@ boost::shared_ptr<piece_picker> setup_picker(
TEST_CHECK(!p->is_finished(piece_block(i, j)));
if ((blocks & (1 << j)) == 0) continue;
++counter;
bool ret = p->mark_as_downloading(piece_block(i, j), (void*)tmp_peer, piece_picker::slow);
bool ret = p->mark_as_downloading(piece_block(i, j), (void*)tmp_peer);
TEST_CHECK(ret == true);
TEST_CHECK(p->is_requested(piece_block(i, j)) == bool(blocks & (1 << j)));
p->mark_as_writing(piece_block(i, j), (void*)tmp_peer);
TEST_CHECK(!p->is_finished(piece_block(i, j)));
// trying to mark a block as requested after it has been completed
// should fail (return false)
ret = p->mark_as_downloading(piece_block(i, j), (void*)tmp_peer, piece_picker::slow);
ret = p->mark_as_downloading(piece_block(i, j), (void*)tmp_peer);
TEST_CHECK(ret == false);
p->mark_as_finished(piece_block(i, j), (void*)tmp_peer);
@ -251,15 +251,14 @@ std::vector<piece_block> pick_pieces(boost::shared_ptr<piece_picker> const& p
, int num_blocks
, int prefer_contiguous_blocks
, void* peer_struct
, piece_picker::piece_state_t state
= piece_picker::fast, int options = piece_picker::rarest_first
, int options = piece_picker::rarest_first
, std::vector<int> const& suggested_pieces = empty_vector)
{
std::vector<piece_block> picked;
counters pc;
p->pick_pieces(string2vec(availability), picked
, num_blocks, prefer_contiguous_blocks, peer_struct
, state, options, suggested_pieces, 20, pc);
, options, suggested_pieces, 20, pc);
print_pick(picked);
TEST_CHECK(verify_pick(p, picked));
return picked;
@ -270,7 +269,7 @@ int test_pick(boost::shared_ptr<piece_picker> const& p
{
const std::vector<int> empty_vector;
std::vector<piece_block> picked = pick_pieces(p, "*******", 1, 0, 0
, piece_picker::fast, options, empty_vector);
, options, empty_vector);
if (picked.empty()) return -1;
return picked[0].piece_index;
}
@ -304,90 +303,88 @@ int test_main()
// test abort_download
print_title("test abort_download");
p = setup_picker("1111111", " ", "7110000", "");
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->abort_download(piece_block(0,0), tmp_peer);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::fast);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
p->mark_as_downloading(piece_block(0,0), &tmp1);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == true);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) == picked.end());
p->abort_download(piece_block(0,0), tmp_peer);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,1), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,0), &tmp1);
p->mark_as_downloading(piece_block(0,1), &tmp1);
p->abort_download(piece_block(0,0), tmp_peer);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,0), &tmp1);
p->mark_as_writing(piece_block(0,0), &tmp1);
p->write_failed(piece_block(0,0));
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(1,0)) != picked.end()
|| std::find(picked.begin(), picked.end(), piece_block(2,0)) != picked.end());
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) == picked.end());
p->restore_piece(0);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,0), &tmp1);
p->mark_as_writing(piece_block(0,0), &tmp1);
p->mark_as_finished(piece_block(0,0), &tmp1);
p->abort_download(piece_block(0,0), tmp_peer);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, tmp_peer
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) == picked.end());
p = setup_picker("1111111", " ", "7110000", "");
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,0), &tmp1);
p->mark_as_finished(piece_block(0,1), 0);
p->piece_info(0, st);
TEST_EQUAL(st.requested, 1);
TEST_EQUAL(st.finished, 1);
TEST_EQUAL(st.state, piece_picker::fast);
p->abort_download(piece_block(0,0), tmp_peer);
p->piece_info(0, st);
TEST_EQUAL(st.requested, 0);
TEST_EQUAL(st.finished, 1);
TEST_EQUAL(st.state, piece_picker::none);
picked = pick_pieces(p, "*******", blocks_per_piece, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", blocks_per_piece, 0, 0
, options, empty_vector);
TEST_CHECK(p->is_requested(piece_block(0, 0)) == false);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(0,0)) != picked.end());
p->mark_as_downloading(piece_block(0, 2), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0, 2), &tmp1);
p->mark_as_writing(piece_block(0, 2), &tmp1);
p->abort_download(piece_block(0, 2), &tmp1);
p->mark_as_downloading(piece_block(0, 2), &tmp2, piece_picker::fast);
p->mark_as_downloading(piece_block(0, 2), &tmp2);
p->mark_as_writing(piece_block(0, 2), &tmp2);
std::vector<void*> d;
p->get_downloaders(d, 0);
TEST_CHECK(d[2] == &tmp2);
p->mark_as_downloading(piece_block(0, 3), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0, 3), &tmp1);
p->abort_download(piece_block(0, 3), &tmp1);
p->mark_as_downloading(piece_block(0, 3), &tmp2, piece_picker::fast);
p->mark_as_downloading(piece_block(0, 3), &tmp2);
p->mark_as_writing(piece_block(0, 3), &tmp2);
p->get_downloaders(d, 0);
@ -397,9 +394,9 @@ int test_main()
for (int i = 0; i < 4; ++i)
for (int k = 0; k < blocks_per_piece; ++k)
p->mark_as_downloading(piece_block(i, k), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(i, k), &tmp1);
p->mark_as_downloading(piece_block(0, 0), &tmp2, piece_picker::fast);
p->mark_as_downloading(piece_block(0, 0), &tmp2);
fprintf(stderr, "num_peers: %d\n", p->num_peers(piece_block(0, 0)));
TEST_EQUAL(p->num_peers(piece_block(0, 0)), 2);
@ -452,7 +449,7 @@ int test_main()
print_title("test reverse rarest first");
p = setup_picker("4179253", " ", "", "");
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, &peer_struct, piece_picker::fast
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, &peer_struct
, piece_picker::rarest_first | piece_picker::reverse, empty_vector);
int expected_common_pieces[] = {3, 2, 5, 0, 6, 4, 1};
for (int i = 0; i < int(picked.size()); ++i)
@ -472,21 +469,21 @@ int test_main()
print_title("test pick whole pieces");
p = setup_picker("2212222", " ", "1111111", "1023460");
picked = pick_pieces(p, "****** ", 1, blocks_per_piece
, &peer_struct, piece_picker::fast, options, empty_vector);
, &peer_struct, options, empty_vector);
TEST_EQUAL(int(picked.size()), 3);
for (int i = 0; i < blocks_per_piece && i < int(picked.size()); ++i)
TEST_EQUAL(picked[i].piece_index, 2);
p = setup_picker("1111111", " ", "1111111", "");
picked = pick_pieces(p, "****** ", 1, blocks_per_piece
, &peer_struct, piece_picker::fast, options, empty_vector);
, &peer_struct, options, empty_vector);
TEST_EQUAL(int(picked.size()), blocks_per_piece);
for (int i = 0; i < blocks_per_piece && i < int(picked.size()); ++i)
TEST_EQUAL(picked[i].block_index, i);
p = setup_picker("2221222", " ", "", "");
picked = pick_pieces(p, "*******", 1, 7 * blocks_per_piece
, &peer_struct, piece_picker::fast, options, empty_vector);
, &peer_struct, options, empty_vector);
TEST_EQUAL(int(picked.size()), 7 * blocks_per_piece);
for (int i = 0; i < int(picked.size()); ++i)
TEST_CHECK(picked[i] == piece_block(i / blocks_per_piece, i % blocks_per_piece));
@ -522,7 +519,7 @@ int test_main()
p->we_dont_have(2);
TEST_CHECK(!p->have_piece(1));
TEST_CHECK(!p->have_piece(2));
picked = pick_pieces(p, "*** ** ", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*** ** ", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front().piece_index == 1);
@ -585,12 +582,12 @@ int test_main()
// make sure requested blocks aren't picked
print_title("test don't pick requested blocks");
p = setup_picker("1111111", " ", "", "");
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
piece_block first = picked.front();
p->mark_as_downloading(picked.front(), &peer_struct, piece_picker::fast);
p->mark_as_downloading(picked.front(), &peer_struct);
TEST_CHECK(p->num_peers(picked.front()) == 1);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() != first);
@ -599,12 +596,12 @@ int test_main()
// make sure downloading pieces have higher priority
print_title("test downloading piece priority");
p = setup_picker("1111111", " ", "", "");
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
first = picked.front();
p->mark_as_downloading(picked.front(), &peer_struct, piece_picker::fast);
p->mark_as_downloading(picked.front(), &peer_struct);
TEST_CHECK(p->num_peers(picked.front()) == 1);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() != first);
TEST_CHECK(picked.front().piece_index == first.piece_index);
@ -625,7 +622,7 @@ int test_main()
// 2. Piece 2 is the best pick in this case.
print_title("test partial piece order (rarest first)");
p = setup_picker("1112111", " ", "", "013700f");
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", 1, 0, 0
, options | piece_picker::prioritize_partials, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() == piece_block(2, 2)
@ -637,7 +634,7 @@ int test_main()
print_title("test partial piece order (most complete)");
p = setup_picker("1111111", " ", "", "013700f");
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", 1, 0, 0
, options | piece_picker::prioritize_partials, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() == piece_block(3, 3));
@ -650,7 +647,7 @@ int test_main()
// make sure the random piece picker can still pick partial pieces
print_title("test random picking (downloading piece)");
p = setup_picker("1111111", " ", "", "013700f");
picked = pick_pieces(p, " *** *", 1, 0, 0, piece_picker::fast
picked = pick_pieces(p, " *** *", 1, 0, 0
, 0, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() == piece_block(1, 1)
@ -661,7 +658,7 @@ int test_main()
// even when prefer_contiguous_blocks is set
print_title("test random picking (downloading piece, prefer contiguous)");
p = setup_picker("1111111", " ", "", "013700f");
picked = pick_pieces(p, " *** *", 1, 4, 0, piece_picker::fast
picked = pick_pieces(p, " *** *", 1, 4, 0
, 0, empty_vector);
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front() == piece_block(1, 1)
@ -674,7 +671,7 @@ int test_main()
// test sequential download
print_title("test sequential download");
p = setup_picker("7654321", " ", "", "");
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0
, piece_picker::sequential, empty_vector);
TEST_CHECK(int(picked.size()) == 7 * blocks_per_piece);
for (int i = 0; i < int(picked.size()); ++i)
@ -685,7 +682,7 @@ int test_main()
// test reverse sequential download
print_title("test reverse sequential download");
p = setup_picker("7654321", " ", "", "");
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0
, piece_picker::sequential | piece_picker::reverse, empty_vector);
TEST_CHECK(int(picked.size()) == 7 * blocks_per_piece);
for (int i = 0; i < int(picked.size()); ++i)
@ -696,7 +693,7 @@ int test_main()
// test priority sequential download
print_title("test priority sequential download");
p = setup_picker("7654321", " ", "1117071", "");
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0, piece_picker::fast
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0
, piece_picker::sequential, empty_vector);
// the piece with priority 0 was not picked, everything else should
@ -783,7 +780,7 @@ int test_main()
p->set_piece_priority(0, 7);
picked = pick_pieces(p, "*******", 7 * blocks_per_piece, 0, 0
, piece_picker::fast, options, empty_vector);
, options, empty_vector);
TEST_CHECK(int(picked.size()) == 7 * blocks_per_piece);
for (int i = 0; i < int(picked.size()); ++i)
@ -817,12 +814,12 @@ int test_main()
p->mark_as_finished(piece_block(0,2), 0);
p->mark_as_finished(piece_block(0,3), 0);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 1);
TEST_CHECK(picked.front().piece_index == 1);
p->restore_piece(0);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 1);
TEST_CHECK(picked.front().piece_index == 0);
@ -832,17 +829,17 @@ int test_main()
p->mark_as_finished(piece_block(0,3), 0);
p->set_piece_priority(0, 0);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 1);
TEST_CHECK(picked.front().piece_index == 1);
p->restore_piece(0);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 1);
TEST_CHECK(picked.front().piece_index == 1);
p->set_piece_priority(0, 7);
picked = pick_pieces(p, "*******", 1, 0, 0, piece_picker::fast, options, empty_vector);
picked = pick_pieces(p, "*******", 1, 0, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 1);
TEST_CHECK(picked.front().piece_index == 0);
@ -865,47 +862,18 @@ int test_main()
}
TEST_CHECK(random_pieces.size() == 7);
// ========================================================
// make sure that blocks from a slow piece are picked
// by a fast peer if there are no other options
print_title("test downloading piece affinity");
p = setup_picker("1111111", " ", "", "");
p->mark_as_downloading(piece_block(2,2), &tmp1, piece_picker::slow);
picked = pick_pieces(p, "*******", 7 * blocks_per_piece - 1, 0, &tmp2
, piece_picker::fast, options | piece_picker::speed_affinity, empty_vector);
TEST_CHECK(picked.size() == 7 * blocks_per_piece - 1);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(2,2)) == picked.end());
// piece 2 sould be the last one (least matching piece to pick)
TEST_CHECK(picked[7 * blocks_per_piece - 2].piece_index == 2);
TEST_CHECK(picked[7 * blocks_per_piece - 3].piece_index == 2);
TEST_CHECK(picked[7 * blocks_per_piece - 4].piece_index == 2);
// test the affinity of pieces with the same speed state
p = setup_picker("1111111", " ", "", "");
p->mark_as_downloading(piece_block(3,2), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(2,2), &tmp1, piece_picker::medium);
p->mark_as_downloading(piece_block(4,2), &tmp1, piece_picker::fast);
picked = pick_pieces(p, "*******", 2 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::prioritize_partials | piece_picker::speed_affinity
, empty_vector);
TEST_CHECK(picked.size() == 2 * blocks_per_piece);
TEST_CHECK(picked[0].piece_index == 4);
TEST_CHECK(picked[blocks_per_piece - 1].piece_index == 2);
TEST_CHECK(picked[2 * blocks_per_piece - 2].piece_index == 3);
// ========================================================
// make sure the piece picker will pick pieces that
// are already requested from other peers if it has to
print_title("test picking downloading blocks");
p = setup_picker("1111111", " ", "", "");
p->mark_as_downloading(piece_block(2,2), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(1,2), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(2,2), &tmp1);
p->mark_as_downloading(piece_block(1,2), &tmp1);
picked.clear();
p->pick_pieces(string2vec("*******"), picked, 7 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::prioritize_partials, empty_vector, 20
, piece_picker::prioritize_partials, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -914,7 +882,7 @@ int test_main()
picked.clear();
p->pick_pieces(string2vec("*******"), picked, 7 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::prioritize_partials
, piece_picker::prioritize_partials
| piece_picker::rarest_first, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
@ -924,7 +892,7 @@ int test_main()
picked.clear();
p->pick_pieces(string2vec("*******"), picked, 7 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::rarest_first, empty_vector, 20
, piece_picker::rarest_first, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -934,7 +902,7 @@ int test_main()
// make sure we still pick from a partial piece even when prefering whole pieces
picked.clear();
p->pick_pieces(string2vec(" * "), picked, 1, blocks_per_piece, 0
, piece_picker::fast, piece_picker::rarest_first
, piece_picker::rarest_first
| piece_picker::align_expanded_pieces, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
@ -947,7 +915,7 @@ int test_main()
picked.clear();
p->lock_piece(1);
p->pick_pieces(string2vec(" ** "), picked, 7, 0, 0
, piece_picker::fast, piece_picker::rarest_first, empty_vector, 20
, piece_picker::rarest_first, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -956,17 +924,17 @@ int test_main()
TEST_CHECK(picked.size() >= 1 && picked[0].piece_index == 2);
p->restore_piece(1);
p->mark_as_downloading(piece_block(2,0), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(2,1), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(2,3), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(1,0), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(1,1), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(1,2), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(1,3), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(2,0), &tmp1);
p->mark_as_downloading(piece_block(2,1), &tmp1);
p->mark_as_downloading(piece_block(2,3), &tmp1);
p->mark_as_downloading(piece_block(1,0), &tmp1);
p->mark_as_downloading(piece_block(1,1), &tmp1);
p->mark_as_downloading(piece_block(1,2), &tmp1);
p->mark_as_downloading(piece_block(1,3), &tmp1);
picked.clear();
p->pick_pieces(string2vec(" ** "), picked, 2, 0, 0
, piece_picker::fast, piece_picker::rarest_first, empty_vector, 20
, piece_picker::rarest_first, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -975,7 +943,7 @@ int test_main()
picked.clear();
p->pick_pieces(string2vec(" ** "), picked, 2 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::prioritize_partials, empty_vector, 0
, piece_picker::prioritize_partials, empty_vector, 0
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -984,7 +952,7 @@ int test_main()
picked.clear();
p->pick_pieces(string2vec(" ** "), picked, 2 * blocks_per_piece, 0, 0
, piece_picker::fast, piece_picker::prioritize_partials, empty_vector, 20
, piece_picker::prioritize_partials, empty_vector, 20
, pc);
TEST_CHECK(verify_pick(p, picked, true));
print_pick(picked);
@ -996,12 +964,12 @@ int test_main()
// test clear_peer
print_title("test clear_peer");
p = setup_picker("1123333", " ", "", "");
p->mark_as_downloading(piece_block(0, 0), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(0, 1), &tmp2, piece_picker::slow);
p->mark_as_downloading(piece_block(0, 2), &tmp3, piece_picker::slow);
p->mark_as_downloading(piece_block(1, 1), &tmp1, piece_picker::slow);
p->mark_as_downloading(piece_block(2, 1), &tmp2, piece_picker::slow);
p->mark_as_downloading(piece_block(3, 1), &tmp3, piece_picker::slow);
p->mark_as_downloading(piece_block(0, 0), &tmp1);
p->mark_as_downloading(piece_block(0, 1), &tmp2);
p->mark_as_downloading(piece_block(0, 2), &tmp3);
p->mark_as_downloading(piece_block(1, 1), &tmp1);
p->mark_as_downloading(piece_block(2, 1), &tmp2);
p->mark_as_downloading(piece_block(3, 1), &tmp3);
std::vector<void*> dls;
void* expected_dls1[] = {&tmp1, &tmp2, &tmp3, 0};
@ -1107,7 +1075,7 @@ int test_main()
TEST_CHECK(p->get_downloader(piece_block(4, 1)) == (void*)tmp_peer);
TEST_CHECK(p->get_downloader(piece_block(4, 2)) == (void*)tmp_peer);
TEST_CHECK(p->get_downloader(piece_block(4, 3)) == 0);
p->mark_as_downloading(piece_block(4, 3), &peer_struct, piece_picker::fast);
p->mark_as_downloading(piece_block(4, 3), &peer_struct);
TEST_CHECK(p->get_downloader(piece_block(4, 3)) == &peer_struct);
p->piece_info(4, st);
TEST_CHECK(st.requested == 1);
@ -1142,7 +1110,7 @@ int test_main()
print_title("test prefer contiguous blocks");
p = setup_picker("1111111", " ", "", "");
picked = pick_pieces(p, "*******", 1, 3 * blocks_per_piece
, 0, piece_picker::fast, options, empty_vector);
, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 3 * blocks_per_piece);
piece_block b = picked.front();
for (int i = 1; i < int(picked.size()); ++i)
@ -1153,7 +1121,7 @@ int test_main()
}
picked = pick_pieces(p, "*******", 1, 3 * blocks_per_piece
, 0, piece_picker::fast, options, empty_vector);
, 0, options, empty_vector);
TEST_CHECK(int(picked.size()) >= 3 * blocks_per_piece);
b = picked.front();
for (int i = 1; i < int(picked.size()); ++i)
@ -1166,9 +1134,9 @@ int test_main()
// make sure pieces that don't match the 'whole pieces' requirement
// are picked if there's no other choice
p = setup_picker("1111111", " ", "", "");
p->mark_as_downloading(piece_block(2,2), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(2,2), &tmp1);
picked = pick_pieces(p, "*******", 7 * blocks_per_piece - 1, blocks_per_piece
, 0, piece_picker::fast, options, empty_vector);
, 0, options, empty_vector);
TEST_CHECK(picked.size() == 7 * blocks_per_piece - 1);
TEST_CHECK(std::find(picked.begin(), picked.end(), piece_block(2,2)) == picked.end());
@ -1176,7 +1144,7 @@ int test_main()
print_title("test prefer aligned whole pieces");
p = setup_picker("2222221222222222", " ", "", "");
picked = pick_pieces(p, "****************", 1, 4 * blocks_per_piece, 0
, piece_picker::fast, options | piece_picker::align_expanded_pieces, empty_vector);
, options | piece_picker::align_expanded_pieces, empty_vector);
// the piece picker should pick piece 5, and then align it to even 4 pieces
// i.e. it should have picked pieces: 4,5,6,7
@ -1201,7 +1169,7 @@ int test_main()
p = setup_picker("3333133", " ", "", "");
p->mark_as_finished(piece_block(0, 0), 0);
picked = pick_pieces(p, "*******", 1, blocks_per_piece, 0
, piece_picker::fast
, options | piece_picker::on_parole | piece_picker::prioritize_partials, empty_vector);
TEST_EQUAL(int(picked.size()), blocks_per_piece - 1);
for (int i = 1; i < int(picked.size()); ++i)
@ -1210,7 +1178,7 @@ int test_main()
// make sure that the partial piece is not picked by a
// peer that is has not downloaded/requested the other blocks
picked = pick_pieces(p, "*******", 1, blocks_per_piece
, &peer_struct, piece_picker::fast
, &peer_struct
, options | piece_picker::on_parole | piece_picker::prioritize_partials, empty_vector);
TEST_EQUAL(int(picked.size()), blocks_per_piece);
for (int i = 1; i < int(picked.size()); ++i)
@ -1225,7 +1193,7 @@ int test_main()
std::vector<int> suggested_pieces(v, v + 2);
picked = pick_pieces(p, "****************", 1, blocks_per_piece
, 0, piece_picker::fast, options, suggested_pieces);
, 0, options, suggested_pieces);
TEST_CHECK(int(picked.size()) >= blocks_per_piece);
for (int i = 1; i < int(picked.size()); ++i)
TEST_CHECK(picked[i] == piece_block(1, i));
@ -1235,14 +1203,14 @@ int test_main()
p->set_piece_priority(3, 0);
picked = pick_pieces(p, "****************", 1, blocks_per_piece
, 0, piece_picker::fast, options, suggested_pieces);
, 0, options, suggested_pieces);
TEST_CHECK(int(picked.size()) >= blocks_per_piece);
for (int i = 1; i < int(picked.size()); ++i)
TEST_CHECK(picked[i] == piece_block(5, i));
p = setup_picker("1111222233334444", "**** ", "", "");
picked = pick_pieces(p, "****************", 1, blocks_per_piece
, 0, piece_picker::fast, options, suggested_pieces);
, 0, options, suggested_pieces);
TEST_CHECK(int(picked.size()) >= blocks_per_piece);
for (int i = 1; i < int(picked.size()); ++i)
TEST_CHECK(picked[i] == piece_block(5, i));
@ -1312,7 +1280,7 @@ int test_main()
// a reversed peer picked a block from piece 0
// This should make the piece reversed
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::slow
p->mark_as_downloading(piece_block(0,0), &tmp1
, piece_picker::reverse);
TEST_EQUAL(test_pick(p, piece_picker::rarest_first), 1);
@ -1328,13 +1296,13 @@ int test_main()
p = setup_picker("3333333", " *****", "", "");
// make piece 0 partial and reversed
p->mark_as_downloading(piece_block(0,1), &tmp1, piece_picker::slow
p->mark_as_downloading(piece_block(0,1), &tmp1
, piece_picker::reverse);
TEST_EQUAL(test_pick(p), 1);
// now have a regular peer pick the reversed block. It should now
// have turned into a regular one and be prioritized
p->mark_as_downloading(piece_block(0,2), &tmp1, piece_picker::fast);
p->mark_as_downloading(piece_block(0,2), &tmp1);
TEST_EQUAL(test_pick(p), 0);
@ -1352,7 +1320,7 @@ int test_main()
// a reversed peer picked a block from piece 0
// This should make the piece reversed
p->mark_as_downloading(piece_block(0,0), &tmp1, piece_picker::slow
p->mark_as_downloading(piece_block(0,0), &tmp1
, piece_picker::reverse);
TEST_EQUAL(test_pick(p, piece_picker::rarest_first | piece_picker::reverse), 0);
@ -1362,21 +1330,21 @@ int test_main()
/*
p.pick_pieces(peer1, picked, 1, false, 0, piece_picker::fast, true);
p.pick_pieces(peer1, picked, 1, false, 0, true);
TEST_CHECK(int(picked.size()) == 1);
TEST_CHECK(picked.front().piece_index == 2);
// now pick a piece from peer2. The block is supposed to be
// from piece 3, since it is the rarest piece that peer has.
picked.clear();
p.pick_pieces(peer2, picked, 1, false, 0, piece_picker::fast, true);
p.pick_pieces(peer2, picked, 1, false, 0, true);
TEST_CHECK(int(picked.size()) == 1);
TEST_CHECK(picked.front().piece_index == 3);
// same thing for peer3.
picked.clear();
p.pick_pieces(peer3, picked, 1, false, 0, piece_picker::fast, true);
p.pick_pieces(peer3, picked, 1, false, 0, true);
TEST_CHECK(int(picked.size()) == 1);
TEST_CHECK(picked.front().piece_index == 5);
@ -1386,7 +1354,7 @@ int test_main()
p.inc_refcount(1);
picked.clear();
p.pick_pieces(peer3, picked, 1, false, 0, piece_picker::fast, true);
p.pick_pieces(peer3, picked, 1, false, 0, true);
TEST_CHECK(int(picked.size()) == 1);
TEST_CHECK(picked.front().piece_index == 1);
// and the block picked should not be 0 or 2
@ -1410,9 +1378,9 @@ int test_main()
// we have block 0 and 2 already, so we can't mark
// them as begin downloaded.
p.mark_as_downloading(piece_block(1, 1), &peer_struct, piece_picker::fast);
p.mark_as_downloading(piece_block(1, 3), &peer_struct, piece_picker::fast);
p.mark_as_downloading(piece_block(2, 0), &peer_struct, piece_picker::fast);
p.mark_as_downloading(piece_block(1, 1), &peer_struct);
p.mark_as_downloading(piece_block(1, 3), &peer_struct);
p.mark_as_downloading(piece_block(2, 0), &peer_struct);
std::vector<piece_picker::downloading_piece> const& downloads = p.get_download_queue();
TEST_CHECK(downloads.size() == 2);
@ -1434,7 +1402,7 @@ int test_main()
TEST_CHECK(!p.is_requested(piece_block(2, 1)));
picked.clear();
p.pick_pieces(peer1, picked, 1, false, 0, piece_picker::fast, true);
p.pick_pieces(peer1, picked, 1, false, 0, true);
TEST_CHECK(int(picked.size()) == 2);
piece_block expected3[] = { piece_block(2, 0), piece_block(2, 1) };
@ -1447,7 +1415,7 @@ int test_main()
// partially selected)
picked.clear();
p.pick_pieces(peer1, picked, 1, true, 0, piece_picker::fast, true);
p.pick_pieces(peer1, picked, 1, true, 0, true);
// it will pick 4 blocks, since we said we
// wanted whole pieces.
@ -1466,7 +1434,7 @@ int test_main()
// to make sure it can still fall back on partial pieces
picked.clear();
p.pick_pieces(peer1, picked, 100, true, 0, piece_picker::fast, true);
p.pick_pieces(peer1, picked, 100, true, 0, true);
TEST_CHECK(int(picked.size()) == 12);
@ -1487,7 +1455,7 @@ int test_main()
// to make sure it can still fall back on partial pieces
picked.clear();
p.pick_pieces(peer1, picked, 100, true, &peer_struct, piece_picker::fast, true);
p.pick_pieces(peer1, picked, 100, true, &peer_struct, true);
TEST_CHECK(int(picked.size()) == 11);