introduce type for slot index in part_file

This commit is contained in:
arvidn 2016-12-25 15:20:17 -08:00 committed by Arvid Norberg
parent 42a27b3ebc
commit cda715c152
4 changed files with 43 additions and 45 deletions

View File

@ -43,6 +43,9 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
struct slot_index_tag_t {};
using slot_index_t = aux::strong_typedef<int, slot_index_tag_t>;
struct TORRENT_EXTRA_EXPORT part_file
{
// create a part file at 'path', that can hold 'num_pieces' pieces.
@ -74,7 +77,7 @@ namespace libtorrent
std::string m_name;
// allocate a slot and return the slot index
int allocate_slot(piece_index_t piece);
slot_index_t allocate_slot(piece_index_t piece);
// this mutex must be held while accessing the data
// structure. Not while reading or writing from the file though!
@ -83,10 +86,10 @@ namespace libtorrent
// this is a list of unallocated slots in the part file
// within the m_num_allocated range
std::vector<int> m_free_slots;
std::vector<slot_index_t> m_free_slots;
// this is the number of slots allocated
int m_num_allocated;
slot_index_t m_num_allocated;
// the max number of pieces in the torrent this part file is
// backing
@ -106,7 +109,7 @@ namespace libtorrent
bool m_dirty_metadata;
// maps a piece index to the part-file slot it is stored in
std::unordered_map<piece_index_t, int> m_piece_map;
std::unordered_map<piece_index_t, slot_index_t> m_piece_map;
// this is the file handle to the part file
file m_file;

View File

@ -701,7 +701,7 @@ std::shared_ptr<torrent_info> make_torrent(bool priv)
ct.add_tracker("http://tracker.com:8080/announce");
for (int i = 0; i < ct.num_pieces(); ++i)
for (piece_index_t i(0); i < piece_index_t(ct.num_pieces()); ++i)
ct.set_hash(i, sha1_hash(nullptr));
ct.set_priv(priv);

View File

@ -57,10 +57,10 @@ add_torrent_params create_torrent(file_storage& fs, bool const pad_files = false
, pad_files ? create_torrent::optimize_alignment : 0);
std::vector<char> piece(piece_size);
int const num = t.num_pieces();
piece_index_t const num = fs.end_piece();
if (pad_files)
{
for (int i = 0; i < num; ++i)
for (piece_index_t i(0); i < num; ++i)
{
std::vector<file_slice> files = fs.map_block(i, 0, fs.piece_size(i));
int k = 0;
@ -92,7 +92,7 @@ add_torrent_params create_torrent(file_storage& fs, bool const pad_files = false
// calculate the hash for all pieces
sha1_hash ph = hasher(&piece[0], int(piece.size())).final();
for (int i = 0; i < num; ++i)
for (piece_index_t i(0); i < num; ++i)
t.set_hash(i, ph);
}
@ -100,7 +100,7 @@ add_torrent_params create_torrent(file_storage& fs, bool const pad_files = false
if ((fs.total_size() % piece_size) > 0)
{
piece.resize(fs.total_size() % piece_size);
t.set_hash(num-1, hasher(&piece[0], int(piece.size())).final());
t.set_hash(prev(num), hasher(&piece[0], int(piece.size())).final());
}
std::vector<char> tmp;
@ -239,7 +239,7 @@ TORRENT_TEST(multi_file)
TEST_CHECK(expected[1]);
}
std::string generate_content(lt::file_storage const& fs, int file
std::string generate_content(lt::file_storage const& fs, file_index_t file
, std::int64_t offset, std::int64_t len)
{
std::string ret;
@ -252,9 +252,9 @@ std::string generate_content(lt::file_storage const& fs, int file
}
void serve_content_for(sim::http_server& http, std::string const& path
, lt::file_storage const& fs, int const file)
, lt::file_storage const& fs, file_index_t const file)
{
http.register_content(path, fs.file_size(file)
http.register_content(path, fs.file_size(file_index_t(file))
, [&fs,file](std::int64_t offset, std::int64_t len)
{ return generate_content(fs, file, offset, len); });
}
@ -294,8 +294,8 @@ TORRENT_TEST(unaligned_file_redirect)
// server for serving the content
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444);
serve_content_for(http2, "/bla/file1", fs, 0);
serve_content_for(http2, "/bar/file2", fs, 1);
serve_content_for(http2, "/bla/file1", fs, file_index_t(0));
serve_content_for(http2, "/bar/file2", fs, file_index_t(1));
sim.run();
}
@ -343,12 +343,12 @@ TORRENT_TEST(multi_file_redirect_pad_files)
// server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444);
serve_content_for(http2, "/bla/file1", fs, 0);
serve_content_for(http2, "/bla/file1", fs, file_index_t(0));
// server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999);
serve_content_for(http3, "/bar/file2", fs, 2);
serve_content_for(http3, "/bar/file2", fs, file_index_t(2));
sim.run();
}
@ -391,12 +391,12 @@ TORRENT_TEST(multi_file_redirect)
// server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444);
serve_content_for(http2, "/bla/file1", fs, 0);
serve_content_for(http2, "/bla/file1", fs, file_index_t(0));
// server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999);
serve_content_for(http3, "/bar/file2", fs, 1);
serve_content_for(http3, "/bar/file2", fs, file_index_t(1));
sim.run();
}
@ -438,12 +438,12 @@ TORRENT_TEST(multi_file_unaligned_redirect)
// server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444);
serve_content_for(http2, "/bla/file1", fs, 0);
serve_content_for(http2, "/bla/file1", fs, file_index_t(0));
// server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999);
serve_content_for(http3, "/bar/file2", fs, 1);
serve_content_for(http3, "/bar/file2", fs, file_index_t(1));
sim.run();
}

View File

@ -64,6 +64,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/part_file.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/aux_/vector.hpp"
namespace
{
@ -113,28 +114,27 @@ namespace libtorrent
// this is used to determine which slots are free, and how many
// slots are allocated
std::vector<bool> free_slots;
aux::vector<bool, slot_index_t> free_slots;
free_slots.resize(num_pieces, true);
for (piece_index_t i = piece_index_t(0); i < piece_index_t(num_pieces); ++i)
{
std::uint32_t const uslot = read_uint32(ptr);
if (uslot == 0xffffffff) continue;
int const slot = int(uslot);
slot_index_t const slot(read_int32(ptr));
if (static_cast<int>(slot) < 0) continue;
// invalid part-file
TORRENT_ASSERT(slot < num_pieces);
if (slot >= num_pieces) continue;
TORRENT_ASSERT(slot < slot_index_t(num_pieces));
if (slot >= slot_index_t(num_pieces)) continue;
if (slot >= m_num_allocated)
m_num_allocated = slot + 1;
m_num_allocated = next(slot);
free_slots[slot] = false;
m_piece_map[i] = slot;
}
// now, populate the free_list with the "holes"
for (int i = 0; i < m_num_allocated; ++i)
for (slot_index_t i(0); i < m_num_allocated; ++i)
{
if (free_slots[i]) m_free_slots.push_back(i);
}
@ -149,12 +149,12 @@ namespace libtorrent
flush_metadata_impl(ec);
}
int part_file::allocate_slot(piece_index_t const piece)
slot_index_t part_file::allocate_slot(piece_index_t const piece)
{
// the mutex is assumed to be held here, since this is a private function
TORRENT_ASSERT(m_piece_map.find(piece) == m_piece_map.end());
int slot = -1;
slot_index_t slot(-1);
if (!m_free_slots.empty())
{
slot = m_free_slots.front();
@ -180,16 +180,13 @@ namespace libtorrent
open_file(file::read_write, ec);
if (ec) return -1;
int slot = -1;
auto const i = m_piece_map.find(piece);
if (i == m_piece_map.end())
slot = allocate_slot(piece);
else
slot = i->second;
slot_index_t const slot = (i == m_piece_map.end())
? allocate_slot(piece) : i->second;
l.unlock();
std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(slot) * m_piece_size;
std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(static_cast<int>(slot)) * m_piece_size;
return int(m_file.writev(slot_offset + offset, bufs, ec));
}
@ -207,14 +204,13 @@ namespace libtorrent
return -1;
}
int slot = i->second;
slot_index_t const slot = i->second;
open_file(file::read_write, ec);
if (ec) return -1;
l.unlock();
std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(slot) * m_piece_size;
std::int64_t slot_offset = std::int64_t(m_header_size) + std::int64_t(static_cast<int>(slot)) * m_piece_size;
return int(m_file.readv(slot_offset + offset, bufs, ec));
}
@ -316,14 +312,14 @@ namespace libtorrent
int const block_to_copy = int(std::min(m_piece_size - piece_offset, size));
if (i != m_piece_map.end())
{
int const slot = i->second;
slot_index_t const slot = i->second;
open_file(file::read_only, ec);
if (ec) return;
if (!buf) buf.reset(new char[m_piece_size]);
std::int64_t const slot_offset = std::int64_t(m_header_size)
+ std::int64_t(slot) * m_piece_size;
+ std::int64_t(static_cast<int>(slot)) * m_piece_size;
// don't hold the lock during disk I/O
l.unlock();
@ -407,10 +403,9 @@ namespace libtorrent
for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece)
{
auto const i = m_piece_map.find(piece);
int const slot = i == m_piece_map.end()
? 0xffffffff
: i->second;
write_uint32(slot, ptr);
slot_index_t const slot(i == m_piece_map.end()
? slot_index_t(-1) : i->second);
write_int32(static_cast<int>(slot), ptr);
}
std::memset(ptr, 0, m_header_size - (ptr - reinterpret_cast<char*>(header.get())));