simplified the piece picker by initializing it properly in its constructor. Removed natpmp reporting port map success when removing mappings. fix where incoming connections before the files were completely checked would cause an assert.

This commit is contained in:
Arvid Norberg 2007-03-16 23:28:26 +00:00
parent d08ca8c4e6
commit 4ac08f393a
6 changed files with 60 additions and 49 deletions

View File

@ -112,18 +112,14 @@ namespace libtorrent
block_info info[max_blocks_per_piece]; block_info info[max_blocks_per_piece];
}; };
piece_picker(int blocks_per_piece
, int total_num_blocks);
void set_sequenced_download_threshold(int sequenced_download_threshold);
// this is called before any other method is called
// after the local files has been checked.
// the vector tells which pieces we already have // the vector tells which pieces we already have
// and which we don't have. // and which we don't have.
void files_checked( piece_picker(int blocks_per_piece
const std::vector<bool>& pieces , int total_num_blocks
, const std::vector<downloading_piece>& unfinished); , std::vector<bool> const& pieces
, std::vector<downloading_piece> const& unfinished);
void set_sequenced_download_threshold(int sequenced_download_threshold);
// increases the peer count for the given piece // increases the peer count for the given piece
// (is used when a HAVE or BITFIELD message is received) // (is used when a HAVE or BITFIELD message is received)
@ -304,8 +300,8 @@ namespace libtorrent
} }
void add(int index); void add(int index);
//TODO: should be renamed update()
void move(int vec_index, int elem_index); void move(int vec_index, int elem_index);
// void remove(int vec_index, int elem_index);
int add_interesting_blocks(const std::vector<int>& piece_list int add_interesting_blocks(const std::vector<int>& piece_list
, const std::vector<bool>& pieces , const std::vector<bool>& pieces
@ -354,9 +350,6 @@ namespace libtorrent
// the required popularity of a piece in order to download // the required popularity of a piece in order to download
// it in sequence instead of random order. // it in sequence instead of random order.
int m_sequenced_download_threshold; int m_sequenced_download_threshold;
#ifndef NDEBUG
bool m_files_checked_called;
#endif
}; };
inline int piece_picker::blocks_in_piece(int index) const inline int piece_picker::blocks_in_piece(int index) const

View File

@ -416,9 +416,17 @@ namespace libtorrent
alert_manager& alerts() const; alert_manager& alerts() const;
piece_picker& picker() piece_picker& picker()
{ {
assert(m_files_checked_called);
assert(!is_seed());
assert(m_picker.get()); assert(m_picker.get());
return *m_picker; return *m_picker;
} }
bool has_picker() const
{
assert((m_files_checked_called && !is_seed())
== bool(m_picker.get()));
return m_picker.get();
}
policy& get_policy() policy& get_policy()
{ {
assert(m_policy); assert(m_policy);
@ -611,6 +619,11 @@ namespace libtorrent
// m_have_pieces.end(), 0) // m_have_pieces.end(), 0)
int m_num_pieces; int m_num_pieces;
// in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep
// its value until the piece picker is created
int m_sequenced_download_threshold;
// is false by default and set to // is false by default and set to
// true when the first tracker reponse // true when the first tracker reponse
// is received // is received
@ -673,6 +686,10 @@ namespace libtorrent
// is started. i.e. // is started. i.e.
// total_done - m_initial_done <= total_payload_download // total_done - m_initial_done <= total_payload_download
size_type m_initial_done; size_type m_initial_done;
// set to true once files_checked has been called
// and the piece picker is constructed
bool m_files_checked_called;
#endif #endif
#ifdef TORRENT_LOGGING #ifdef TORRENT_LOGGING

View File

@ -307,11 +307,15 @@ void natpmp::on_reply(asio::error_code const& e
throw std::runtime_error(errmsg.str()); throw std::runtime_error(errmsg.str());
} }
int tcp_port = 0; // don't report when we remove mappings
int udp_port = 0; if (m.local_port != 0)
if (m.protocol == 1) udp_port = m.external_port; {
else tcp_port = public_port; int tcp_port = 0;
m_callback(tcp_port, udp_port, ""); int udp_port = 0;
if (m.protocol == 1) udp_port = m.external_port;
else tcp_port = public_port;
m_callback(tcp_port, udp_port, "");
}
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@ -687,7 +687,7 @@ namespace libtorrent
// just remember the bitmask // just remember the bitmask
// don't update the piecepicker // don't update the piecepicker
// (since it doesn't exist yet) // (since it doesn't exist yet)
if (!t->valid_metadata()) if (!t->ready_for_connections())
{ {
m_have_piece = bitfield; m_have_piece = bitfield;
m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true); m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true);

View File

@ -52,7 +52,9 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent namespace libtorrent
{ {
piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks) piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks
, std::vector<bool> const& pieces
, std::vector<downloading_piece> const& unfinished)
: m_piece_info(2) : m_piece_info(2)
, m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece) , m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece)
, m_num_filtered(0) , m_num_filtered(0)
@ -61,9 +63,6 @@ namespace libtorrent
{ {
assert(blocks_per_piece > 0); assert(blocks_per_piece > 0);
assert(total_num_blocks >= 0); assert(total_num_blocks >= 0);
#ifndef NDEBUG
m_files_checked_called = false;
#endif
// the piece index is stored in 20 bits, which limits the allowed // the piece index is stored in 20 bits, which limits the allowed
// number of pieces somewhat // number of pieces somewhat
@ -82,16 +81,8 @@ namespace libtorrent
// and make them invalid (as if though we already had every piece) // and make them invalid (as if though we already had every piece)
std::fill(m_piece_map.begin(), m_piece_map.end() std::fill(m_piece_map.begin(), m_piece_map.end()
, piece_pos(0, piece_pos::we_have_index)); , piece_pos(0, piece_pos::we_have_index));
}
// pieces is a bitmask with the pieces we have
void piece_picker::files_checked(
const std::vector<bool>& pieces
, const std::vector<downloading_piece>& unfinished)
{
#ifndef NDEBUG
m_files_checked_called = true;
#endif
for (std::vector<bool>::const_iterator i = pieces.begin(); for (std::vector<bool>::const_iterator i = pieces.begin();
i != pieces.end(); ++i) i != pieces.end(); ++i)
{ {
@ -126,6 +117,7 @@ namespace libtorrent
} }
} }
} }
} }
void piece_picker::set_sequenced_download_threshold( void piece_picker::set_sequenced_download_threshold(
@ -376,7 +368,6 @@ namespace libtorrent
{ {
assert(priority > 0); assert(priority > 0);
assert(elem_index >= 0); assert(elem_index >= 0);
assert(m_files_checked_called);
assert(int(m_piece_info.size()) > priority); assert(int(m_piece_info.size()) > priority);
assert(int(m_piece_info[priority].size()) > elem_index); assert(int(m_piece_info[priority].size()) > elem_index);
@ -532,7 +523,6 @@ namespace libtorrent
assert(index >= 0); assert(index >= 0);
assert(index < (int)m_piece_map.size()); assert(index < (int)m_piece_map.size());
assert(m_files_checked_called);
assert(m_piece_map[index].downloading == 1); assert(m_piece_map[index].downloading == 1);
@ -554,7 +544,6 @@ namespace libtorrent
// TORRENT_PIECE_PICKER_INVARIANT_CHECK; // TORRENT_PIECE_PICKER_INVARIANT_CHECK;
assert(i >= 0); assert(i >= 0);
assert(i < (int)m_piece_map.size()); assert(i < (int)m_piece_map.size());
assert(m_files_checked_called);
piece_pos& p = m_piece_map[i]; piece_pos& p = m_piece_map[i];
int index = p.index; int index = p.index;
@ -587,7 +576,6 @@ namespace libtorrent
{ {
// TORRENT_PIECE_PICKER_INVARIANT_CHECK; // TORRENT_PIECE_PICKER_INVARIANT_CHECK;
assert(m_files_checked_called);
assert(i >= 0); assert(i >= 0);
assert(i < (int)m_piece_map.size()); assert(i < (int)m_piece_map.size());
@ -754,7 +742,6 @@ namespace libtorrent
TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_PIECE_PICKER_INVARIANT_CHECK;
assert(num_blocks > 0); assert(num_blocks > 0);
assert(pieces.size() == m_piece_map.size()); assert(pieces.size() == m_piece_map.size());
assert(m_files_checked_called);
// free refers to pieces that are free to download, no one else // free refers to pieces that are free to download, no one else
// is downloading them. // is downloading them.

View File

@ -256,6 +256,7 @@ namespace libtorrent
, m_time_scaler(0) , m_time_scaler(0)
, m_priority(.5) , m_priority(.5)
, m_num_pieces(0) , m_num_pieces(0)
, m_sequenced_download_threshold(0)
, m_got_tracker_response(false) , m_got_tracker_response(false)
, m_ratio(0.f) , m_ratio(0.f)
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
@ -270,6 +271,7 @@ namespace libtorrent
{ {
#ifndef NDEBUG #ifndef NDEBUG
m_initial_done = 0; m_initial_done = 0;
m_files_checked_called = false;
#endif #endif
#ifdef TORRENT_LOGGING #ifdef TORRENT_LOGGING
m_log = ses.create_log("torrent_" m_log = ses.create_log("torrent_"
@ -346,6 +348,7 @@ namespace libtorrent
, m_time_scaler(0) , m_time_scaler(0)
, m_priority(.5) , m_priority(.5)
, m_num_pieces(0) , m_num_pieces(0)
, m_sequenced_download_threshold(0)
, m_got_tracker_response(false) , m_got_tracker_response(false)
, m_ratio(0.f) , m_ratio(0.f)
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
@ -360,6 +363,7 @@ namespace libtorrent
{ {
#ifndef NDEBUG #ifndef NDEBUG
m_initial_done = 0; m_initial_done = 0;
m_files_checked_called = false;
#endif #endif
#ifdef TORRENT_LOGGING #ifdef TORRENT_LOGGING
@ -459,9 +463,6 @@ namespace libtorrent
m_storage.reset(new piece_manager(m_torrent_file, m_save_path m_storage.reset(new piece_manager(m_torrent_file, m_save_path
, m_ses.m_files, m_storage_constructor)); , m_ses.m_files, m_storage_constructor));
m_block_size = calculate_block_size(m_torrent_file, m_default_block_size); m_block_size = calculate_block_size(m_torrent_file, m_default_block_size);
m_picker.reset(new piece_picker(
static_cast<int>(m_torrent_file.piece_length() / m_block_size)
, static_cast<int>((m_torrent_file.total_size()+m_block_size-1)/m_block_size)));
std::vector<std::string> const& url_seeds = m_torrent_file.url_seeds(); std::vector<std::string> const& url_seeds = m_torrent_file.url_seeds();
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
@ -701,10 +702,9 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
if (!valid_metadata()) return tuple<size_type, size_type>(0,0); if (!has_picker() || m_torrent_file.num_pieces() == 0)
if (m_torrent_file.num_pieces() == 0)
return tuple<size_type, size_type>(0,0); return tuple<size_type, size_type>(0,0);
const int last_piece = m_torrent_file.num_pieces() - 1; const int last_piece = m_torrent_file.num_pieces() - 1;
if (is_seed()) if (is_seed())
@ -2132,11 +2132,17 @@ namespace libtorrent
if (!is_seed()) if (!is_seed())
{ {
m_picker->files_checked(m_have_pieces, unfinished_pieces); m_picker.reset(new piece_picker(
static_cast<int>(m_torrent_file.piece_length() / m_block_size)
, static_cast<int>((m_torrent_file.total_size()+m_block_size-1)/m_block_size)
, m_have_pieces, unfinished_pieces));
m_files_checked_called = true;
if (m_sequenced_download_threshold > 0)
picker().set_sequenced_download_threshold(m_sequenced_download_threshold);
} }
else else
{ {
m_picker.reset(); assert(!m_picker);
} }
if (!m_connections_initialized) if (!m_connections_initialized)
{ {
@ -2267,10 +2273,14 @@ namespace libtorrent
void torrent::set_sequenced_download_threshold(int threshold) void torrent::set_sequenced_download_threshold(int threshold)
{ {
// TODO: if there is not valid metadata, save this setting and if (has_picker())
// set it once the piece picker is created. {
if (valid_metadata() && !is_seed())
picker().set_sequenced_download_threshold(threshold); picker().set_sequenced_download_threshold(threshold);
}
else
{
m_sequenced_download_threshold = threshold;
}
} }