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 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 struct TORRENT_EXTRA_EXPORT part_file
{ {
// create a part file at 'path', that can hold 'num_pieces' pieces. // create a part file at 'path', that can hold 'num_pieces' pieces.
@ -74,7 +77,7 @@ namespace libtorrent
std::string m_name; std::string m_name;
// allocate a slot and return the slot index // 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 // this mutex must be held while accessing the data
// structure. Not while reading or writing from the file though! // 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 // this is a list of unallocated slots in the part file
// within the m_num_allocated range // 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 // 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 // the max number of pieces in the torrent this part file is
// backing // backing
@ -106,7 +109,7 @@ namespace libtorrent
bool m_dirty_metadata; bool m_dirty_metadata;
// maps a piece index to the part-file slot it is stored in // 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 // this is the file handle to the part file
file m_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"); 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_hash(i, sha1_hash(nullptr));
ct.set_priv(priv); 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); , pad_files ? create_torrent::optimize_alignment : 0);
std::vector<char> piece(piece_size); std::vector<char> piece(piece_size);
int const num = t.num_pieces(); piece_index_t const num = fs.end_piece();
if (pad_files) 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)); std::vector<file_slice> files = fs.map_block(i, 0, fs.piece_size(i));
int k = 0; 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 // calculate the hash for all pieces
sha1_hash ph = hasher(&piece[0], int(piece.size())).final(); 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); 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) if ((fs.total_size() % piece_size) > 0)
{ {
piece.resize(fs.total_size() % piece_size); 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; std::vector<char> tmp;
@ -239,7 +239,7 @@ TORRENT_TEST(multi_file)
TEST_CHECK(expected[1]); 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::int64_t offset, std::int64_t len)
{ {
std::string ret; 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 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) , [&fs,file](std::int64_t offset, std::int64_t len)
{ return generate_content(fs, file, offset, len); }); { return generate_content(fs, file, offset, len); });
} }
@ -294,8 +294,8 @@ TORRENT_TEST(unaligned_file_redirect)
// server for serving the content // server for serving the content
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3")); sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444); 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));
serve_content_for(http2, "/bar/file2", fs, 1); serve_content_for(http2, "/bar/file2", fs, file_index_t(1));
sim.run(); sim.run();
} }
@ -343,12 +343,12 @@ TORRENT_TEST(multi_file_redirect_pad_files)
// server for file 1 // server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3")); sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444); 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 // server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4")); sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999); 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(); sim.run();
} }
@ -391,12 +391,12 @@ TORRENT_TEST(multi_file_redirect)
// server for file 1 // server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3")); sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444); 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 // server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4")); sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999); 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(); sim.run();
} }
@ -438,12 +438,12 @@ TORRENT_TEST(multi_file_unaligned_redirect)
// server for file 1 // server for file 1
sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3")); sim::asio::io_service web_server2(sim, address_v4::from_string("3.3.3.3"));
sim::http_server http2(web_server2, 4444); 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 // server for file 2
sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4")); sim::asio::io_service web_server3(sim, address_v4::from_string("4.4.4.4"));
sim::http_server http3(web_server3, 9999); 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(); sim.run();
} }

View File

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