forked from premiere/premiere-libtorrent
deallocates the piece picker when seeding, to free up unused memory
This commit is contained in:
parent
7fa3d899a1
commit
90feac8126
|
@ -297,17 +297,35 @@ namespace libtorrent
|
|||
// piece a peer has gained.
|
||||
void peer_has(int index)
|
||||
{
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
||||
m_picker->inc_refcount(index);
|
||||
if (m_picker.get())
|
||||
{
|
||||
assert(!is_seed());
|
||||
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
||||
m_picker->inc_refcount(index);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
else
|
||||
{
|
||||
assert(is_seed());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// when peer disconnects, this is called for every piece it had
|
||||
void peer_lost(int index)
|
||||
{
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
||||
m_picker->dec_refcount(index);
|
||||
if (m_picker.get())
|
||||
{
|
||||
assert(!is_seed());
|
||||
assert(index >= 0 && index < (signed)m_have_pieces.size());
|
||||
m_picker->dec_refcount(index);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
else
|
||||
{
|
||||
assert(is_seed());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int block_size() const { assert(m_block_size > 0); return m_block_size; }
|
||||
|
|
|
@ -595,19 +595,22 @@ namespace libtorrent
|
|||
m_peer_choked = true;
|
||||
t->get_policy().choked(*this);
|
||||
|
||||
// remove all pieces from this peers download queue and
|
||||
// remove the 'downloading' flag from piece_picker.
|
||||
for (std::deque<piece_block>::iterator i = m_download_queue.begin();
|
||||
i != m_download_queue.end(); ++i)
|
||||
if (!t->is_seed())
|
||||
{
|
||||
t->picker().abort_download(*i);
|
||||
}
|
||||
for (std::deque<piece_block>::const_iterator i = m_request_queue.begin()
|
||||
, end(m_request_queue.end()); i != end; ++i)
|
||||
{
|
||||
// since this piece was skipped, clear it and allow it to
|
||||
// be requested from other peers
|
||||
t->picker().abort_download(*i);
|
||||
// remove all pieces from this peers download queue and
|
||||
// remove the 'downloading' flag from piece_picker.
|
||||
for (std::deque<piece_block>::iterator i = m_download_queue.begin();
|
||||
i != m_download_queue.end(); ++i)
|
||||
{
|
||||
t->picker().abort_download(*i);
|
||||
}
|
||||
for (std::deque<piece_block>::const_iterator i = m_request_queue.begin()
|
||||
, end(m_request_queue.end()); i != end; ++i)
|
||||
{
|
||||
// since this piece was skipped, clear it and allow it to
|
||||
// be requested from other peers
|
||||
t->picker().abort_download(*i);
|
||||
}
|
||||
}
|
||||
m_download_queue.clear();
|
||||
m_request_queue.clear();
|
||||
|
@ -717,13 +720,16 @@ namespace libtorrent
|
|||
m_have_piece[index] = true;
|
||||
|
||||
// only update the piece_picker if
|
||||
// we have the metadata
|
||||
// we have the metadata and if
|
||||
// we're not a seed (in which case
|
||||
// we won't have a piece picker)
|
||||
if (t->valid_metadata())
|
||||
{
|
||||
++m_num_pieces;
|
||||
t->peer_has(index);
|
||||
|
||||
if (!t->have_piece(index)
|
||||
&& !t->is_seed()
|
||||
&& !is_interesting()
|
||||
&& !t->picker().is_filtered(index))
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
|
@ -797,14 +803,17 @@ namespace libtorrent
|
|||
// let the torrent know which pieces the
|
||||
// peer has, in a shuffled order
|
||||
bool interesting = false;
|
||||
for (std::vector<int>::reverse_iterator i = piece_list.rbegin();
|
||||
i != piece_list.rend(); ++i)
|
||||
if (!t->is_seed())
|
||||
{
|
||||
int index = *i;
|
||||
t->peer_has(index);
|
||||
if (!t->have_piece(index)
|
||||
&& !t->picker().is_filtered(index))
|
||||
interesting = true;
|
||||
for (std::vector<int>::reverse_iterator i = piece_list.rbegin();
|
||||
i != piece_list.rend(); ++i)
|
||||
{
|
||||
int index = *i;
|
||||
t->peer_has(index);
|
||||
if (!t->have_piece(index)
|
||||
&& !t->picker().is_filtered(index))
|
||||
interesting = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (piece_list.size() == m_have_piece.size())
|
||||
|
@ -1420,7 +1429,7 @@ namespace libtorrent
|
|||
|
||||
if (t)
|
||||
{
|
||||
if (t->valid_metadata())
|
||||
if (t->valid_metadata() && !t->is_seed())
|
||||
{
|
||||
piece_picker& picker = t->picker();
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace
|
|||
, peer_connection& c
|
||||
, std::vector<peer_connection*> ignore = std::vector<peer_connection*>())
|
||||
{
|
||||
assert(!t.is_seed());
|
||||
int num_requests = c.desired_queue_size()
|
||||
- (int)c.download_queue().size()
|
||||
- (int)c.request_queue().size();
|
||||
|
|
|
@ -465,8 +465,8 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
seed_random_generator()
|
||||
{
|
||||
std::srand((unsigned int)boost::posix_time::microsec_clock::
|
||||
universal_time().time_of_day().total_microseconds());
|
||||
std::srand((unsigned int)(boost::posix_time::microsec_clock::
|
||||
universal_time().time_of_day().total_microseconds()));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -658,10 +658,11 @@ namespace libtorrent
|
|||
|
||||
if (!valid_metadata()) return 0;
|
||||
|
||||
assert(m_picker.get());
|
||||
|
||||
if (m_torrent_file.num_pieces() == 0)
|
||||
return 0;
|
||||
|
||||
if (is_seed()) return m_torrent_file.total_size();
|
||||
|
||||
const int last_piece = m_torrent_file.num_pieces() - 1;
|
||||
|
||||
size_type total_done
|
||||
|
@ -688,12 +689,14 @@ namespace libtorrent
|
|||
|
||||
if (!valid_metadata()) return tuple<size_type, size_type>(0,0);
|
||||
|
||||
assert(m_picker.get());
|
||||
|
||||
if (m_torrent_file.num_pieces() == 0)
|
||||
return tuple<size_type, size_type>(0,0);
|
||||
const int last_piece = m_torrent_file.num_pieces() - 1;
|
||||
|
||||
if (is_seed())
|
||||
return make_tuple(m_torrent_file.total_size()
|
||||
, m_torrent_file.total_size());
|
||||
|
||||
size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered())
|
||||
* m_torrent_file.piece_length();
|
||||
|
||||
|
@ -880,7 +883,6 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
|
||||
|
@ -911,6 +913,7 @@ namespace libtorrent
|
|||
try { (*i)->on_piece_pass(index); } catch (std::exception&) {}
|
||||
}
|
||||
#endif
|
||||
if (is_seed()) m_picker.reset();
|
||||
}
|
||||
|
||||
std::string torrent::tracker_login() const
|
||||
|
@ -1560,7 +1563,14 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_picker->files_checked(m_have_pieces, unfinished_pieces);
|
||||
if (!is_seed())
|
||||
{
|
||||
m_picker->files_checked(m_have_pieces, unfinished_pieces);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_picker.reset();
|
||||
}
|
||||
if (!m_connections_initialized)
|
||||
{
|
||||
m_connections_initialized = true;
|
||||
|
@ -1662,12 +1672,15 @@ namespace libtorrent
|
|||
assert(m_priority >= 0.f && m_priority < 1.f);
|
||||
assert(!valid_metadata() || m_block_size > 0);
|
||||
assert(!valid_metadata() || (m_torrent_file.piece_length() % m_block_size) == 0);
|
||||
// if (is_seed()) assert(m_picker.get() == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void torrent::set_sequenced_download_threshold(int threshold)
|
||||
{
|
||||
if (valid_metadata())
|
||||
// TODO: if there is not valid metadata, save this setting and
|
||||
// set it once the piece picker is created.
|
||||
if (valid_metadata() && !is_seed())
|
||||
picker().set_sequenced_download_threshold(threshold);
|
||||
}
|
||||
|
||||
|
@ -2040,6 +2053,7 @@ namespace libtorrent
|
|||
|
||||
assert(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0)
|
||||
== m_num_pieces);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2199,7 +2213,10 @@ namespace libtorrent
|
|||
st.state = torrent_status::downloading;
|
||||
|
||||
st.num_seeds = num_seeds();
|
||||
st.distributed_copies = m_picker->distributed_copies();
|
||||
if (m_picker.get())
|
||||
st.distributed_copies = m_picker->distributed_copies();
|
||||
else
|
||||
st.distributed_copies = -1;
|
||||
return st;
|
||||
}
|
||||
|
||||
|
|
|
@ -455,57 +455,61 @@ namespace libtorrent
|
|||
entry::list_type& slots = ret["slots"].list();
|
||||
std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots));
|
||||
|
||||
const piece_picker& p = t->picker();
|
||||
|
||||
const std::vector<piece_picker::downloading_piece>& q
|
||||
= p.get_download_queue();
|
||||
|
||||
// blocks per piece
|
||||
int num_blocks_per_piece =
|
||||
static_cast<int>(t->torrent_file().piece_length()) / t->block_size();
|
||||
ret["blocks per piece"] = num_blocks_per_piece;
|
||||
|
||||
// unfinished pieces
|
||||
ret["unfinished"] = entry::list_type();
|
||||
entry::list_type& up = ret["unfinished"].list();
|
||||
|
||||
// info for each unfinished piece
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i
|
||||
= q.begin(); i != q.end(); ++i)
|
||||
// if this torrent is a seed, we won't have a piece picker
|
||||
// and there will be no half-finished pieces.
|
||||
if (!t->is_seed())
|
||||
{
|
||||
if (i->finished_blocks.count() == 0) continue;
|
||||
const piece_picker& p = t->picker();
|
||||
|
||||
entry piece_struct(entry::dictionary_t);
|
||||
const std::vector<piece_picker::downloading_piece>& q
|
||||
= p.get_download_queue();
|
||||
|
||||
// the unfinished piece's index
|
||||
piece_struct["piece"] = i->index;
|
||||
// blocks per piece
|
||||
int num_blocks_per_piece =
|
||||
static_cast<int>(t->torrent_file().piece_length()) / t->block_size();
|
||||
ret["blocks per piece"] = num_blocks_per_piece;
|
||||
|
||||
std::string bitmask;
|
||||
const int num_bitmask_bytes
|
||||
= std::max(num_blocks_per_piece / 8, 1);
|
||||
// unfinished pieces
|
||||
ret["unfinished"] = entry::list_type();
|
||||
entry::list_type& up = ret["unfinished"].list();
|
||||
|
||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||
// info for each unfinished piece
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i
|
||||
= q.begin(); i != q.end(); ++i)
|
||||
{
|
||||
unsigned char v = 0;
|
||||
for (int k = 0; k < 8; ++k)
|
||||
v |= i->finished_blocks[j*8+k]?(1 << k):0;
|
||||
bitmask.insert(bitmask.end(), v);
|
||||
if (i->finished_blocks.count() == 0) continue;
|
||||
|
||||
entry piece_struct(entry::dictionary_t);
|
||||
|
||||
// the unfinished piece's index
|
||||
piece_struct["piece"] = i->index;
|
||||
|
||||
std::string bitmask;
|
||||
const int num_bitmask_bytes
|
||||
= std::max(num_blocks_per_piece / 8, 1);
|
||||
|
||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||
{
|
||||
unsigned char v = 0;
|
||||
for (int k = 0; k < 8; ++k)
|
||||
v |= i->finished_blocks[j*8+k]?(1 << k):0;
|
||||
bitmask.insert(bitmask.end(), v);
|
||||
}
|
||||
piece_struct["bitmask"] = bitmask;
|
||||
|
||||
assert(t->filesystem().slot_for_piece(i->index) >= 0);
|
||||
unsigned long adler
|
||||
= t->filesystem().piece_crc(
|
||||
t->filesystem().slot_for_piece(i->index)
|
||||
, t->block_size()
|
||||
, i->finished_blocks);
|
||||
|
||||
piece_struct["adler32"] = adler;
|
||||
|
||||
// push the struct onto the unfinished-piece list
|
||||
up.push_back(piece_struct);
|
||||
}
|
||||
piece_struct["bitmask"] = bitmask;
|
||||
|
||||
assert(t->filesystem().slot_for_piece(i->index) >= 0);
|
||||
unsigned long adler
|
||||
= t->filesystem().piece_crc(
|
||||
t->filesystem().slot_for_piece(i->index)
|
||||
, t->block_size()
|
||||
, i->finished_blocks);
|
||||
|
||||
piece_struct["adler32"] = adler;
|
||||
|
||||
// push the struct onto the unfinished-piece list
|
||||
up.push_back(piece_struct);
|
||||
}
|
||||
|
||||
// write local peers
|
||||
|
||||
ret["peers"] = entry::list_type();
|
||||
|
@ -704,6 +708,8 @@ namespace libtorrent
|
|||
queue.clear();
|
||||
if (!t) return;
|
||||
if (!t->valid_metadata()) return;
|
||||
// if we're a seed, the piece picker has been removed
|
||||
if (t->is_seed()) return;
|
||||
|
||||
const piece_picker& p = t->picker();
|
||||
|
||||
|
|
Loading…
Reference in New Issue