added support for torrents with odd piece sizes

This commit is contained in:
Arvid Norberg 2010-02-23 16:26:24 +00:00
parent 5c5f1d23a9
commit eff49e42a7
9 changed files with 28 additions and 52 deletions

View File

@ -106,7 +106,7 @@
* improved LSD performance and made the interval configurable * improved LSD performance and made the interval configurable
* improved UDP tracker support by caching connect tokens * improved UDP tracker support by caching connect tokens
* fast piece optimization * fast piece optimization
* fixed error handling with torrents with invalid piece sizes * added support for torrents with odd piece sizes
* fixed issue with disk read cache not being cleared when removing torrents * fixed issue with disk read cache not being cleared when removing torrents
release 0.14.9 release 0.14.9

View File

@ -6275,8 +6275,7 @@ code symbol description
------ ----------------------------------------- ----------------------------------------------------------------- ------ ----------------------------------------- -----------------------------------------------------------------
81 packet_too_large The packet size exceeded the upper sanity check-limit 81 packet_too_large The packet size exceeded the upper sanity check-limit
------ ----------------------------------------- ----------------------------------------------------------------- ------ ----------------------------------------- -----------------------------------------------------------------
82 torrent_invalid_piece_size The .torrent file has an invalid piece size. It needs to be an 82 reserved
even 16 kiB multiple
------ ----------------------------------------- ----------------------------------------------------------------- ------ ----------------------------------------- -----------------------------------------------------------------
83 http_error The web server responded with an error 83 http_error The web server responded with an error
------ ----------------------------------------- ----------------------------------------------------------------- ------ ----------------------------------------- -----------------------------------------------------------------

View File

@ -139,7 +139,7 @@ namespace libtorrent
duplicate_peer_id, duplicate_peer_id,
torrent_removed, torrent_removed,
packet_too_large, packet_too_large,
torrent_invalid_piece_size, reserved,
http_error, http_error,
missing_location, missing_location,
invalid_redirection, invalid_redirection,

View File

@ -192,7 +192,7 @@ namespace libtorrent
int sparse_regions() const { return m_sparse_regions; } int sparse_regions() const { return m_sparse_regions; }
// sets all pieces to dont-have // sets all pieces to dont-have
void init(int blocks_per_piece, int total_num_blocks); void init(int blocks_per_piece, int blocks_in_last_piece, int total_num_pieces);
int num_pieces() const { return int(m_piece_map.size()); } int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const bool have_piece(int index) const

View File

@ -559,7 +559,7 @@ namespace libtorrent
} }
int block_size() const { TORRENT_ASSERT(m_block_size_shift > 0); return 1 << m_block_size_shift; } int block_size() const { TORRENT_ASSERT(m_block_size_shift > 0); return 1 << m_block_size_shift; }
peer_request to_req(piece_block const& p); peer_request to_req(piece_block const& p) const;
void disconnect_all(error_code const& ec); void disconnect_all(error_code const& ec);
int disconnect_peers(int num); int disconnect_peers(int num);

View File

@ -130,7 +130,7 @@ namespace libtorrent
"duplicate peer-id", "duplicate peer-id",
"torrent removed", "torrent removed",
"packet too large", "packet too large",
"invalid piece size in torrent file", "",
"HTTP error", "HTTP error",
"missing location header", "missing location header",
"invalid redirection", "invalid redirection",

View File

@ -1037,19 +1037,10 @@ namespace libtorrent
torrent_info const& ti = t->torrent_file(); torrent_info const& ti = t->torrent_file();
return p.piece >= 0 return p.piece >= 0
&& p.piece < t->torrent_file().num_pieces() && p.piece < ti.num_pieces()
&& p.length >= 0
&& p.start >= 0 && p.start >= 0
&& (p.length == t->block_size() && p.start < ti.piece_length()
|| (p.length < t->block_size() && t->to_req(piece_block(p.piece, p.start / t->block_size())) == p;
&& p.piece == ti.num_pieces()-1
&& p.start + p.length == ti.piece_size(p.piece))
|| (m_request_large_blocks
&& p.length <= ti.piece_length() * (m_prefer_whole_pieces == 0 ?
1 : m_prefer_whole_pieces)))
&& p.piece * size_type(ti.piece_length()) + p.start + p.length
<= ti.total_size()
&& (p.start % t->block_size() == 0);
} }
void peer_connection::attach_to_torrent(sha1_hash const& ih) void peer_connection::attach_to_torrent(sha1_hash const& ih)
@ -2088,7 +2079,7 @@ namespace libtorrent
if (!t->is_seed()) if (!t->is_seed())
{ {
const int blocks_per_piece = static_cast<int>( const int blocks_per_piece = static_cast<int>(
t->torrent_file().piece_length() / t->block_size()); (t->torrent_file().piece_length() + t->block_size() - 1) / t->block_size());
std::vector<piece_picker::downloading_piece> const& dl_queue std::vector<piece_picker::downloading_piece> const& dl_queue
= t->picker().get_download_queue(); = t->picker().get_download_queue();
@ -2216,9 +2207,7 @@ namespace libtorrent
std::vector<piece_block> finished_blocks; std::vector<piece_block> finished_blocks;
piece_block block_finished(p.piece, p.start / t->block_size()); piece_block block_finished(p.piece, p.start / t->block_size());
TORRENT_ASSERT(p.start % t->block_size() == 0); TORRENT_ASSERT(verify_piece(p));
TORRENT_ASSERT(p.length == t->block_size()
|| p.length == t->torrent_file().total_size() % t->block_size());
std::vector<pending_block>::iterator b std::vector<pending_block>::iterator b
= std::find_if( = std::find_if(
@ -4967,13 +4956,9 @@ namespace libtorrent
in_download_queue = true; in_download_queue = true;
outstanding_bytes += p->full_block_bytes - m_received_in_piece; outstanding_bytes += p->full_block_bytes - m_received_in_piece;
} }
else if (i->block == last_block)
{
outstanding_bytes += last_block_size;
}
else else
{ {
outstanding_bytes += block_size; outstanding_bytes += t->to_req(i->block).length;
} }
} }
//if (p && p->bytes_downloaded < p->full_block_bytes) TORRENT_ASSERT(in_download_queue); //if (p && p->bytes_downloaded < p->full_block_bytes) TORRENT_ASSERT(in_download_queue);

View File

@ -76,18 +76,17 @@ namespace libtorrent
#endif #endif
} }
void piece_picker::init(int blocks_per_piece, int total_num_blocks) void piece_picker::init(int blocks_per_piece, int blocks_in_last_piece, int total_num_pieces)
{ {
TORRENT_ASSERT(blocks_per_piece > 0); TORRENT_ASSERT(blocks_per_piece > 0);
TORRENT_ASSERT(total_num_blocks >= 0); TORRENT_ASSERT(total_num_pieces > 0);
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cerr << "piece_picker::init()" << std::endl; std::cerr << "piece_picker::init()" << std::endl;
#endif #endif
// allocate the piece_map to cover all pieces // allocate the piece_map to cover all pieces
// and make them invalid (as if we don't have a single piece) // and make them invalid (as if we don't have a single piece)
m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece m_piece_map.resize(total_num_pieces, piece_pos(0, 0));
, piece_pos(0, 0));
m_reverse_cursor = int(m_piece_map.size()); m_reverse_cursor = int(m_piece_map.size());
m_cursor = 0; m_cursor = 0;
@ -118,7 +117,7 @@ namespace libtorrent
TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index); TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index);
m_blocks_per_piece = blocks_per_piece; m_blocks_per_piece = blocks_per_piece;
m_blocks_in_last_piece = total_num_blocks % blocks_per_piece; m_blocks_in_last_piece = blocks_in_last_piece;
if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece; if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece;
TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece); TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece);

View File

@ -744,7 +744,7 @@ namespace libtorrent
return m_torrent_file->add_merkle_nodes(nodes, piece); return m_torrent_file->add_merkle_nodes(nodes, piece);
} }
peer_request torrent::to_req(piece_block const& p) peer_request torrent::to_req(piece_block const& p) const
{ {
int block_offset = p.block_index * block_size(); int block_offset = p.block_index * block_size();
int block = (std::min)(torrent_file().piece_size( int block = (std::min)(torrent_file().piece_size(
@ -817,14 +817,6 @@ namespace libtorrent
return; return;
} }
if (m_torrent_file->piece_length() % block_size() != 0)
{
// TODO: try to adjust the block size
set_error(errors::torrent_invalid_piece_size, "");
pause();
return;
}
// the shared_from_this() will create an intentional // the shared_from_this() will create an intentional
// cycle of ownership, se the hpp file for description. // cycle of ownership, se the hpp file for description.
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
@ -834,8 +826,10 @@ namespace libtorrent
if (has_picker()) if (has_picker())
{ {
m_picker->init((std::max)(m_torrent_file->piece_length() / block_size(), 1) int blocks_per_piece = (m_torrent_file->piece_length() + block_size() - 1) / block_size();
, int((m_torrent_file->total_size()+block_size()-1) / block_size())); int blocks_in_last_piece = ((m_torrent_file->total_size() % m_torrent_file->piece_length())
+ block_size() - 1) / block_size();
m_picker->init(blocks_per_piece, blocks_in_last_piece, m_torrent_file->num_pieces());
} }
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds(); std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
@ -1153,8 +1147,11 @@ namespace libtorrent
m_owning_storage->async_release_files(); m_owning_storage->async_release_files();
if (!m_picker) m_picker.reset(new piece_picker()); if (!m_picker) m_picker.reset(new piece_picker());
std::fill(m_file_progress.begin(), m_file_progress.end(), 0); std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
m_picker->init(m_torrent_file->piece_length() / block_size()
, int((m_torrent_file->total_size() + block_size()-1)/block_size())); int blocks_per_piece = (m_torrent_file->piece_length() + block_size() - 1) / block_size();
int blocks_in_last_piece = ((m_torrent_file->total_size() % m_torrent_file->piece_length())
+ block_size() - 1) / block_size();
m_picker->init(blocks_per_piece, blocks_in_last_piece, m_torrent_file->num_pieces());
// assume that we don't have anything // assume that we don't have anything
TORRENT_ASSERT(m_picker->num_have() == 0); TORRENT_ASSERT(m_picker->num_have() == 0);
m_files_checked = false; m_files_checked = false;
@ -1972,11 +1969,8 @@ namespace libtorrent
} }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes); TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
if (p->piece_index == last_piece_index TORRENT_ASSERT(p->full_block_bytes == to_req(piece_block(
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size()) p->piece_index, p->block_index)).length);
TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
else
TORRENT_ASSERT(p->full_block_bytes == block_size());
#endif #endif
} }
for (std::map<piece_block, int>::iterator i = downloading_piece.begin(); for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
@ -4856,7 +4850,6 @@ namespace libtorrent
if (m_files_checked && valid_metadata()) if (m_files_checked && valid_metadata())
{ {
TORRENT_ASSERT(block_size() > 0); TORRENT_ASSERT(block_size() > 0);
TORRENT_ASSERT((m_torrent_file->piece_length() & (block_size()-1)) == 0);
} }
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0); // if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);