deallocates the piece picker when seeding, to free up unused memory

This commit is contained in:
Arvid Norberg 2006-12-04 12:20:34 +00:00
parent 7fa3d899a1
commit 90feac8126
6 changed files with 131 additions and 80 deletions

View File

@ -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; }

View File

@ -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();

View File

@ -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();

View File

@ -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()));
}
};

View File

@ -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;
}

View File

@ -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();