make super-seeding a bit more robust

This commit is contained in:
Arvid Norberg 2012-04-23 05:48:46 +00:00
parent a7f1d7df91
commit 49f74be42f
5 changed files with 62 additions and 36 deletions

View File

@ -275,8 +275,12 @@ namespace libtorrent
// this will tell the peer to announce the given piece
// and only allow it to request that piece
void superseed_piece(int index);
int superseed_piece() const { return m_superseed_piece; }
void superseed_piece(int replace_piece, int new_piece);
bool super_seeded_piece(int index) const
{
return m_superseed_piece[0] == index
|| m_superseed_piece[1] == index;
}
// tells if this connection has data it want to send
// and has enough upload bandwidth quota left to send it.
@ -993,12 +997,12 @@ namespace libtorrent
// once the connection completes
int m_connection_ticket;
// if this is -1, superseeding is not active. If it is >= 0
// if [0] is -1, superseeding is not active. If it is >= 0
// this is the piece that is available to this peer. Only
// this piece can be downloaded from us by this peer.
// these two pieces can be downloaded from us by this peer.
// This will remain the current piece for this peer until
// another peer sends us a have message for this piece
int m_superseed_piece;
int m_superseed_piece[2];
// bytes downloaded since last second
// timer timeout; used for determining

View File

@ -492,7 +492,10 @@ namespace libtorrent
void get_suggested_pieces(std::vector<int>& s) const;
bool super_seeding() const
{ return m_super_seeding; }
{
// we're not super seeding if we're not a seed
return m_super_seeding && is_seed();
}
void super_seeding(bool on);
int get_piece_to_super_seed(bitfield const&);

View File

@ -338,6 +338,10 @@ namespace libtorrent
if (!m_supports_fast) return;
#ifdef TORRENT_VERBOSE_LOGGING
peer_log("==> REJECT_PIECE [ piece: %d | s: %d | l: %d ]"
, r.piece, r.start, r.length);
#endif
TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield);
TORRENT_ASSERT(associated_torrent().lock()->valid_metadata());
@ -1989,9 +1993,9 @@ namespace libtorrent
m_sent_bitfield = true;
#endif
// bootstrap superseeding by sending one have message
superseed_piece(t->get_piece_to_super_seed(
get_bitfield()));
// bootstrap superseeding by sending two have message
superseed_piece(-1, t->get_piece_to_super_seed(get_bitfield()));
superseed_piece(-1, t->get_piece_to_super_seed(get_bitfield()));
return;
}
else if (m_supports_fast && t->is_seed())

View File

@ -158,7 +158,6 @@ namespace libtorrent
, m_peer_info(peerinfo)
, m_speed(slow)
, m_connection_ticket(-1)
, m_superseed_piece(-1)
, m_remote_bytes_dled(0)
, m_remote_dl_rate(0)
, m_outstanding_writing_bytes(0)
@ -202,6 +201,8 @@ namespace libtorrent
, m_received_in_piece(0)
#endif
{
m_superseed_piece[0] = -1;
m_superseed_piece[1] = -1;
boost::shared_ptr<torrent> t = m_torrent.lock();
// if t is NULL, we better not be connecting, since
// we can't decrement the connecting counter
@ -311,7 +312,6 @@ namespace libtorrent
, m_peer_info(peerinfo)
, m_speed(slow)
, m_connection_ticket(-1)
, m_superseed_piece(-1)
, m_remote_bytes_dled(0)
, m_remote_dl_rate(0)
, m_outstanding_writing_bytes(0)
@ -355,6 +355,8 @@ namespace libtorrent
, m_received_in_piece(0)
#endif
{
m_superseed_piece[0] = -1;
m_superseed_piece[1] = -1;
m_est_reciprocation_rate = m_ses.m_settings.default_est_reciprocation_rate;
#if TORRENT_USE_I2P
@ -1661,11 +1663,11 @@ namespace libtorrent
}
}
if (t->super_seeding() && m_superseed_piece != -1)
if (t->super_seeding())
{
// assume the peer has the piece we're superseeding to it
// and give it another one
if (!m_have_piece[m_superseed_piece]) incoming_have(m_superseed_piece);
// maybe we need to try another piece, to see if the peer
// is interested in us then
superseed_piece(-1, t->get_piece_to_super_seed(m_have_piece));
}
}
@ -1733,9 +1735,9 @@ namespace libtorrent
// if the peer optimizes out redundant have messages
// this will be handled when the peer sends not-interested
// instead.
if (m_superseed_piece == index)
if (super_seeded_piece(index))
{
superseed_piece(t->get_piece_to_super_seed(m_have_piece));
superseed_piece(index, t->get_piece_to_super_seed(m_have_piece));
}
}
@ -1798,15 +1800,15 @@ namespace libtorrent
// a new piece to that peer
if (t->super_seeding()
&& m_ses.settings().strict_super_seeding
&& (index != m_superseed_piece || t->num_peers() == 1))
&& (!super_seeded_piece(index) || t->num_peers() == 1))
{
for (torrent::peer_iterator i = t->begin()
, end(t->end()); i != end; ++i)
{
peer_connection* p = *i;
if (p->superseed_piece() != index) continue;
if (!p->super_seeded_piece(index)) continue;
if (!p->has_piece(index)) continue;
p->superseed_piece(t->get_piece_to_super_seed(p->get_bitfield()));
p->superseed_piece(index, t->get_piece_to_super_seed(p->get_bitfield()));
}
}
}
@ -2034,8 +2036,8 @@ namespace libtorrent
, r.piece, r.start, r.length);
#endif
if (m_superseed_piece != -1
&& r.piece != m_superseed_piece)
if (t->super_seeding()
&& !super_seeded_piece(r.piece))
{
#ifdef TORRENT_STATS
++m_ses.m_invalid_piece_requests;
@ -2043,14 +2045,17 @@ namespace libtorrent
++m_num_invalid_requests;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
peer_log("*** INVALID_REQUEST [ piece not superseeded "
"i: %d t: %d n: %d h: %d ss: %d ]"
"i: %d t: %d n: %d h: %d ss1: %d ss2: %d ]"
, m_peer_interested
, int(t->torrent_file().piece_size(r.piece))
, t->torrent_file().num_pieces()
, t->have_piece(r.piece)
, m_superseed_piece);
, m_superseed_piece[0]
, m_superseed_piece[1]);
#endif
write_reject_request(r);
if (t->alerts().should_post<invalid_request_alert>())
{
t->alerts().post_alert(invalid_request_alert(
@ -3990,12 +3995,13 @@ namespace libtorrent
m_packet_size = packet_size;
}
void peer_connection::superseed_piece(int index)
void peer_connection::superseed_piece(int replace_piece, int new_piece)
{
if (index == -1)
if (new_piece == -1)
{
if (m_superseed_piece == -1) return;
m_superseed_piece = -1;
if (m_superseed_piece[0] == -1) return;
m_superseed_piece[0] = -1;
m_superseed_piece[1] = -1;
#ifdef TORRENT_VERBOSE_LOGGING
peer_log("*** ending super seed mode");
@ -4003,6 +4009,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
assert(t);
// TODO: we should probably just send a HAVE_ALL here
for (int i = 0; i < int(m_have_piece.size()); ++i)
{
if (m_have_piece[i] || !t->have_piece(i)) continue;
@ -4015,13 +4022,22 @@ namespace libtorrent
return;
}
assert(!has_piece(index));
assert(!has_piece(new_piece));
#ifdef TORRENT_VERBOSE_LOGGING
peer_log("==> HAVE [ piece: %d ] (super seed)", index);
peer_log("==> HAVE [ piece: %d ] (super seed)", new_piece);
#endif
write_have(index);
m_superseed_piece = index;
write_have(new_piece);
if (replace_piece >= 0)
{
// move the piece we're replacing to the tail
if (m_superseed_piece[0] == replace_piece)
std::swap(m_superseed_piece[0], m_superseed_piece[1]);
}
m_superseed_piece[1] = m_superseed_piece[0];
m_superseed_piece[0] = new_piece;
}
void peer_connection::update_desired_queue_size()

View File

@ -923,8 +923,6 @@ namespace libtorrent
// been closed by the time the torrent is destructed. And they are
// supposed to be closed. So we can still do the invariant check.
TORRENT_ASSERT(m_connections.empty());
INVARIANT_CHECK;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING || defined TORRENT_LOGGING
@ -932,6 +930,7 @@ namespace libtorrent
#endif
TORRENT_ASSERT(m_abort);
TORRENT_ASSERT(m_connections.empty());
if (!m_connections.empty())
disconnect_all(errors::torrent_aborted);
}
@ -3474,7 +3473,7 @@ namespace libtorrent
// disable super seeding for all peers
for (peer_iterator i = begin(); i != end(); ++i)
{
(*i)->superseed_piece(-1);
(*i)->superseed_piece(-1, -1);
}
}
@ -3495,7 +3494,7 @@ namespace libtorrent
int availability = 0;
for (const_peer_iterator j = begin(); j != end(); ++j)
{
if ((*j)->superseed_piece() == i)
if ((*j)->super_seeded_piece(i))
{
// avoid superseeding the same piece to more than one
// peer if we can avoid it. Do this by artificially