From c8088459a036d5e1f772235cbd90cb9057e23818 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 1 Sep 2007 03:00:31 +0000 Subject: [PATCH] made torrent_info reference counted and held by a boost::intrusive_ptr --- examples/make_torrent.cpp | 22 +-- include/libtorrent/aux_/session_impl.hpp | 2 +- include/libtorrent/intrusive_ptr_base.hpp | 3 + include/libtorrent/session.hpp | 8 + include/libtorrent/storage.hpp | 25 +-- include/libtorrent/torrent.hpp | 12 +- include/libtorrent/torrent_info.hpp | 3 +- src/session.cpp | 13 ++ src/session_impl.cpp | 14 +- src/storage.cpp | 162 ++++++++++--------- src/torrent.cpp | 186 +++++++++++----------- test/test_storage.cpp | 34 ++-- test/test_web_seed.cpp | 18 +-- 13 files changed, 264 insertions(+), 238 deletions(-) diff --git a/examples/make_torrent.cpp b/examples/make_torrent.cpp index 7915ab96f..72d9f2e62 100644 --- a/examples/make_torrent.cpp +++ b/examples/make_torrent.cpp @@ -87,39 +87,39 @@ int main(int argc, char* argv[]) try { - torrent_info t; + boost::intrusive_ptr t(new torrent_info); path full_path = complete(path(argv[3])); ofstream out(complete(path(argv[1])), std::ios_base::binary); int piece_size = 256 * 1024; char const* creator_str = "libtorrent"; - add_files(t, full_path.branch_path(), full_path.leaf()); - t.set_piece_size(piece_size); + add_files(*t, full_path.branch_path(), full_path.leaf()); + t->set_piece_size(piece_size); file_pool fp; boost::scoped_ptr st( default_storage_constructor(t, full_path.branch_path(), fp)); - t.add_tracker(argv[2]); + t->add_tracker(argv[2]); // calculate the hash for all pieces - int num = t.num_pieces(); + int num = t->num_pieces(); std::vector buf(piece_size); for (int i = 0; i < num; ++i) { - st->read(&buf[0], i, 0, t.piece_size(i)); - hasher h(&buf[0], t.piece_size(i)); - t.set_hash(i, h.final()); + st->read(&buf[0], i, 0, t->piece_size(i)); + hasher h(&buf[0], t->piece_size(i)); + t->set_hash(i, h.final()); std::cerr << (i+1) << "/" << num << "\r"; } - t.set_creator(creator_str); + t->set_creator(creator_str); if (argc == 5) - t.add_url_seed(argv[4]); + t->add_url_seed(argv[4]); // create the torrent and print it to out - entry e = t.create_torrent(); + entry e = t->create_torrent(); libtorrent::bencode(std::ostream_iterator(out), e); } catch (std::exception& e) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index e0962bf06..74ca7c8f7 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -240,7 +240,7 @@ namespace libtorrent bool is_listening() const; torrent_handle add_torrent( - torrent_info const& ti + boost::intrusive_ptr ti , fs::path const& save_path , entry const& resume_data , bool compact_mode diff --git a/include/libtorrent/intrusive_ptr_base.hpp b/include/libtorrent/intrusive_ptr_base.hpp index a432bc350..39ba2e77f 100644 --- a/include/libtorrent/intrusive_ptr_base.hpp +++ b/include/libtorrent/intrusive_ptr_base.hpp @@ -42,6 +42,9 @@ namespace libtorrent template struct intrusive_ptr_base { + intrusive_ptr_base(const intrusive_ptr_base& b) + : m_refs(0) {} + friend void intrusive_ptr_add_ref(intrusive_ptr_base const* s) { assert(s->m_refs >= 0); diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 7451f5915..a7ccc8d57 100755 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -142,6 +142,14 @@ namespace libtorrent , entry const& resume_data = entry() , bool compact_mode = true , bool paused = false + , storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED; + + torrent_handle add_torrent( + boost::intrusive_ptr ti + , fs::path const& save_path + , entry const& resume_data = entry() + , bool compact_mode = true + , bool paused = false , storage_constructor_type sc = default_storage_constructor); torrent_handle add_torrent( diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 8a10c7148..8cdab5476 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #ifdef _MSC_VER @@ -147,10 +148,11 @@ namespace libtorrent }; typedef storage_interface* (&storage_constructor_type)( - torrent_info const&, fs::path const& + boost::intrusive_ptr, fs::path const& , file_pool&); - TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti + TORRENT_EXPORT storage_interface* default_storage_constructor( + boost::intrusive_ptr ti , fs::path const& path, file_pool& fp); // returns true if the filesystem the path relies on supports @@ -169,7 +171,7 @@ namespace libtorrent piece_manager( boost::shared_ptr const& torrent - , torrent_info const& ti + , boost::intrusive_ptr ti , fs::path const& path , file_pool& fp , disk_io_thread& io @@ -227,7 +229,7 @@ namespace libtorrent { return m_compact_mode; } #ifndef NDEBUG - std::string name() const { return m_info.name(); } + std::string name() const { return m_info->name(); } #endif private: @@ -283,7 +285,7 @@ namespace libtorrent // a bitmask representing the pieces we have std::vector m_have_piece; - torrent_info const& m_info; + boost::intrusive_ptr m_info; // slots that haven't had any file storage allocated std::vector m_unallocated_slots; @@ -313,12 +315,6 @@ namespace libtorrent mutable boost::recursive_mutex m_mutex; - bool m_allocating; - boost::mutex m_allocating_monitor; - boost::condition m_allocating_condition; - - // these states are used while checking/allocating the torrent - enum { // the default initial state state_none, @@ -333,6 +329,11 @@ namespace libtorrent } m_state; int m_current_slot; + // this is saved in case we need to instantiate a new + // storage (osed when remapping files) + storage_constructor_type m_storage_constructor; + + // temporary buffer used while checking std::vector m_piece_data; // this maps a piece hash to piece index. It will be @@ -340,6 +341,8 @@ namespace libtorrent // isn't needed) std::multimap m_hash_to_piece; + // this map contains partial hashes for downloading + // pieces. std::map m_piece_hasher; disk_io_thread& m_io_thread; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index dabc34141..b8f8d7ae4 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -97,7 +97,7 @@ namespace libtorrent torrent( aux::session_impl& ses , aux::checker_impl& checker - , torrent_info const& tf + , boost::intrusive_ptr tf , fs::path const& save_path , tcp::endpoint const& net_interface , bool compact_mode @@ -469,14 +469,14 @@ namespace libtorrent bool is_seed() const { return valid_metadata() - && m_num_pieces == m_torrent_file.num_pieces(); + && m_num_pieces == m_torrent_file->num_pieces(); } // this is true if we have all the pieces that we want bool is_finished() const { if (is_seed()) return true; - return valid_metadata() && m_torrent_file.num_pieces() + return valid_metadata() && m_torrent_file->num_pieces() - m_num_pieces - m_picker->num_filtered() == 0; } @@ -498,7 +498,7 @@ namespace libtorrent } piece_manager& filesystem(); torrent_info const& torrent_file() const - { return m_torrent_file; } + { return *m_torrent_file; } std::vector const& trackers() const { return m_trackers; } @@ -539,7 +539,7 @@ namespace libtorrent bool ready_for_connections() const { return m_connections_initialized; } bool valid_metadata() const - { return m_torrent_file.is_valid(); } + { return m_torrent_file->is_valid(); } // parses the info section from the given // bencoded tree and moves the torrent @@ -563,7 +563,7 @@ namespace libtorrent void update_peer_interest(); - torrent_info m_torrent_file; + boost::intrusive_ptr m_torrent_file; // is set to true when the torrent has // been aborted. diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 795289bf4..093d33781 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -57,6 +57,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_request.hpp" #include "libtorrent/config.hpp" #include "libtorrent/time.hpp" +#include "libtorrent/intrusive_ptr_base.hpp" namespace libtorrent { @@ -96,7 +97,7 @@ namespace libtorrent virtual const char* what() const throw() { return "invalid torrent file"; } }; - class TORRENT_EXPORT torrent_info + class TORRENT_EXPORT torrent_info : public intrusive_ptr_base { public: diff --git a/src/session.cpp b/src/session.cpp index 8175cbdfe..818af3ada 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -181,6 +181,19 @@ namespace libtorrent , bool compact_mode , bool paused , storage_constructor_type sc) + { + boost::intrusive_ptr tip(new torrent_info(ti)); + return m_impl->add_torrent(tip, save_path, resume_data + , compact_mode, sc, paused); + } + + torrent_handle session::add_torrent( + boost::intrusive_ptr ti + , fs::path const& save_path + , entry const& resume_data + , bool compact_mode + , bool paused + , storage_constructor_type sc) { return m_impl->add_torrent(ti, save_path, resume_data , compact_mode, sc, paused); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 125664302..730ee7aaa 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1454,7 +1454,7 @@ namespace detail } torrent_handle session_impl::add_torrent( - torrent_info const& ti + boost::intrusive_ptr ti , fs::path const& save_path , entry const& resume_data , bool compact_mode @@ -1466,7 +1466,7 @@ namespace detail assert(m_external_listen_port > 0); assert(!save_path.empty()); - if (ti.begin_files() == ti.end_files()) + if (ti->begin_files() == ti->end_files()) throw std::runtime_error("no files in torrent"); // lock the session and the checker thread (the order is important!) @@ -1479,11 +1479,11 @@ namespace detail throw std::runtime_error("session is closing"); // is the torrent already active? - if (!find_torrent(ti.info_hash()).expired()) + if (!find_torrent(ti->info_hash()).expired()) throw duplicate_torrent(); // is the torrent currently being checked? - if (m_checker_impl.find_torrent(ti.info_hash())) + if (m_checker_impl.find_torrent(ti->info_hash())) throw duplicate_torrent(); // create the torrent and the data associated with @@ -1508,13 +1508,13 @@ namespace detail new aux::piece_checker_data); d->torrent_ptr = torrent_ptr; d->save_path = save_path; - d->info_hash = ti.info_hash(); + d->info_hash = ti->info_hash(); d->resume_data = resume_data; #ifndef TORRENT_DISABLE_DHT if (m_dht) { - torrent_info::nodes_t const& nodes = ti.nodes(); + torrent_info::nodes_t const& nodes = ti->nodes(); std::for_each(nodes.begin(), nodes.end(), bind( (void(dht::dht_tracker::*)(std::pair const&)) &dht::dht_tracker::add_node @@ -1528,7 +1528,7 @@ namespace detail // job in its queue m_checker_impl.m_cond.notify_one(); - return torrent_handle(this, &m_checker_impl, ti.info_hash()); + return torrent_handle(this, &m_checker_impl, ti->info_hash()); } torrent_handle session_impl::add_torrent( diff --git a/src/storage.cpp b/src/storage.cpp index 64f601927..1cce6ad81 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -345,11 +345,11 @@ namespace libtorrent class storage : public storage_interface, boost::noncopyable { public: - storage(torrent_info const& info, fs::path const& path, file_pool& fp) + storage(boost::intrusive_ptr info, fs::path const& path, file_pool& fp) : m_info(info) , m_files(fp) { - assert(info.begin_files(true) != info.end_files(true)); + assert(info->begin_files(true) != info->end_files(true)); m_save_path = fs::complete(path); assert(m_save_path.is_complete()); } @@ -369,11 +369,9 @@ namespace libtorrent size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero); ~storage() - { - m_files.release(this); - } + { m_files.release(this); } - torrent_info const& m_info; + boost::intrusive_ptr m_info; fs::path m_save_path; // the file pool is typically stored in // the session, to make all storage @@ -412,8 +410,8 @@ namespace libtorrent { // first, create all missing directories fs::path last_path; - for (torrent_info::file_iterator file_iter = m_info.begin_files(true), - end_iter = m_info.end_files(true); file_iter != end_iter; ++file_iter) + for (torrent_info::file_iterator file_iter = m_info->begin_files(true), + end_iter = m_info->end_files(true); file_iter != end_iter; ++file_iter) { fs::path dir = (m_save_path / file_iter->path).branch_path(); @@ -461,7 +459,7 @@ namespace libtorrent void storage::write_resume_data(entry& rd) const { std::vector > file_sizes - = get_filesizes(m_info, m_save_path); + = get_filesizes(*m_info, m_save_path); rd["file sizes"] = entry::list_type(); entry::list_type& fl = rd["file sizes"].list(); @@ -495,7 +493,7 @@ namespace libtorrent } entry::list_type& slots = rd["slots"].list(); - bool seed = int(slots.size()) == m_info.num_pieces() + bool seed = int(slots.size()) == m_info->num_pieces() && std::find_if(slots.begin(), slots.end() , boost::bind(std::less() , boost::bind((size_type const& (entry::*)() const) @@ -510,11 +508,11 @@ namespace libtorrent if (seed) { - if (m_info.num_files(true) != (int)file_sizes.size()) + if (m_info->num_files(true) != (int)file_sizes.size()) { error = "the number of files does not match the torrent (num: " + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(m_info.num_files(true)) + ")"; + + boost::lexical_cast(m_info->num_files(true)) + ")"; return false; } @@ -522,8 +520,8 @@ namespace libtorrent fs = file_sizes.begin(); // the resume data says we have the entire torrent // make sure the file sizes are the right ones - for (torrent_info::file_iterator i = m_info.begin_files(true) - , end(m_info.end_files(true)); i != end; ++i, ++fs) + for (torrent_info::file_iterator i = m_info->begin_files(true) + , end(m_info->end_files(true)); i != end; ++i, ++fs) { if (i->size != fs->first) { @@ -536,7 +534,7 @@ namespace libtorrent return true; } - return match_filesizes(m_info, m_save_path, file_sizes + return match_filesizes(*m_info, m_save_path, file_sizes , !full_allocation_mode, &error); } @@ -575,11 +573,11 @@ namespace libtorrent m_files.release(this); #if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 - old_path = safe_convert((m_save_path / m_info.name()).string()); - new_path = safe_convert((save_path / m_info.name()).string()); + old_path = safe_convert((m_save_path / m_info->name()).string()); + new_path = safe_convert((save_path / m_info->name()).string()); #else - old_path = m_save_path / m_info.name(); - new_path = save_path / m_info.name(); + old_path = m_save_path / m_info->name(); + new_path = save_path / m_info->name(); #endif try @@ -601,7 +599,7 @@ namespace libtorrent /* void storage::shuffle() { - int num_pieces = m_info.num_pieces(); + int num_pieces = m_info->num_pieces(); std::vector pieces(num_pieces); for (std::vector::iterator i = pieces.begin(); @@ -618,7 +616,7 @@ namespace libtorrent { const int slot_index = targets[i]; const int piece_index = pieces[i]; - const int slot_size =static_cast(m_info.piece_size(slot_index)); + const int slot_size =static_cast(m_info->piece_size(slot_index)); std::vector buf(slot_size); read(&buf[0], piece_index, 0, slot_size); write(&buf[0], slot_index, 0, slot_size); @@ -629,7 +627,7 @@ namespace libtorrent void storage::move_slot(int src_slot, int dst_slot) { - int piece_size = m_info.piece_size(dst_slot); + int piece_size = m_info->piece_size(dst_slot); m_scratch_buffer.resize(piece_size); read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true); write(&m_scratch_buffer[0], dst_slot, 0, piece_size); @@ -638,9 +636,9 @@ namespace libtorrent void storage::swap_slots(int slot1, int slot2) { // the size of the target slot is the size of the piece - int piece_size = m_info.piece_length(); - int piece1_size = m_info.piece_size(slot2); - int piece2_size = m_info.piece_size(slot1); + int piece_size = m_info->piece_length(); + int piece1_size = m_info->piece_size(slot2); + int piece2_size = m_info->piece_size(slot1); m_scratch_buffer.resize(piece_size * 2); read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); @@ -651,10 +649,10 @@ namespace libtorrent void storage::swap_slots3(int slot1, int slot2, int slot3) { // the size of the target slot is the size of the piece - int piece_size = m_info.piece_length(); - int piece1_size = m_info.piece_size(slot2); - int piece2_size = m_info.piece_size(slot3); - int piece3_size = m_info.piece_size(slot1); + int piece_size = m_info->piece_length(); + int piece1_size = m_info->piece_size(slot2); + int piece2_size = m_info->piece_size(slot3); + int piece3_size = m_info->piece_size(slot1); m_scratch_buffer.resize(piece_size * 2); read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); @@ -681,25 +679,25 @@ namespace libtorrent , bool fill_zero) { assert(buf != 0); - assert(slot >= 0 && slot < m_info.num_pieces()); + assert(slot >= 0 && slot < m_info->num_pieces()); assert(offset >= 0); - assert(offset < m_info.piece_size(slot)); + assert(offset < m_info->piece_size(slot)); assert(size > 0); #ifndef NDEBUG std::vector slices - = m_info.map_block(slot, offset, size, true); + = m_info->map_block(slot, offset, size, true); assert(!slices.empty()); #endif - size_type start = slot * (size_type)m_info.piece_length() + offset; - assert(start + size <= m_info.total_size()); + size_type start = slot * (size_type)m_info->piece_length() + offset; + assert(start + size <= m_info->total_size()); // find the file iterator and file offset size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info.begin_files(true);;) + for (file_iter = m_info->begin_files(true);;) { if (file_offset < file_iter->size) break; @@ -732,7 +730,7 @@ namespace libtorrent #endif int left_to_read = size; - int slot_size = static_cast(m_info.piece_size(slot)); + int slot_size = static_cast(m_info->piece_size(slot)); if (offset + left_to_read > slot_size) left_to_read = slot_size - offset; @@ -757,7 +755,7 @@ namespace libtorrent assert(int(slices.size()) > counter); size_type slice_size = slices[counter].size; assert(slice_size == read_bytes); - assert(m_info.file_at(slices[counter].file_index, true).path + assert(m_info->file_at(slices[counter].file_index, true).path == file_iter->path); #endif @@ -807,30 +805,30 @@ namespace libtorrent { assert(buf != 0); assert(slot >= 0); - assert(slot < m_info.num_pieces()); + assert(slot < m_info->num_pieces()); assert(offset >= 0); assert(size > 0); #ifndef NDEBUG std::vector slices - = m_info.map_block(slot, offset, size, true); + = m_info->map_block(slot, offset, size, true); assert(!slices.empty()); #endif - size_type start = slot * (size_type)m_info.piece_length() + offset; + size_type start = slot * (size_type)m_info->piece_length() + offset; // find the file iterator and file offset size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info.begin_files(true);;) + for (file_iter = m_info->begin_files(true);;) { if (file_offset < file_iter->size) break; file_offset -= file_iter->size; ++file_iter; - assert(file_iter != m_info.end_files(true)); + assert(file_iter != m_info->end_files(true)); } fs::path p(m_save_path / file_iter->path); @@ -850,7 +848,7 @@ namespace libtorrent } int left_to_write = size; - int slot_size = static_cast(m_info.piece_size(slot)); + int slot_size = static_cast(m_info->piece_size(slot)); if (offset + left_to_write > slot_size) left_to_write = slot_size - offset; @@ -874,7 +872,7 @@ namespace libtorrent { assert(int(slices.size()) > counter); assert(slices[counter].size == write_bytes); - assert(m_info.file_at(slices[counter].file_index, true).path + assert(m_info->file_at(slices[counter].file_index, true).path == file_iter->path); assert(buf_pos >= 0); @@ -902,7 +900,7 @@ namespace libtorrent #endif ++file_iter; - assert(file_iter != m_info.end_files(true)); + assert(file_iter != m_info->end_files(true)); fs::path p = m_save_path / file_iter->path; file_offset = 0; out = m_files.open_file( @@ -913,7 +911,7 @@ namespace libtorrent } } - storage_interface* default_storage_constructor(torrent_info const& ti + storage_interface* default_storage_constructor(boost::intrusive_ptr ti , fs::path const& path, file_pool& fp) { return new storage(ti, path, fp); @@ -1027,7 +1025,7 @@ namespace libtorrent piece_manager::piece_manager( boost::shared_ptr const& torrent - , torrent_info const& ti + , boost::intrusive_ptr ti , fs::path const& save_path , file_pool& fp , disk_io_thread& io @@ -1037,7 +1035,7 @@ namespace libtorrent , m_fill_mode(true) , m_info(ti) , m_save_path(complete(save_path)) - , m_allocating(false) + , m_storage_constructor(sc) , m_io_thread(io) , m_torrent(torrent) { @@ -1140,7 +1138,7 @@ namespace libtorrent int slot = m_piece_to_slot[piece]; assert(slot != has_no_slot); - return m_storage->hash_for_slot(slot, ph, m_info.piece_size(piece)); + return m_storage->hash_for_slot(slot, ph, m_info->piece_size(piece)); } void piece_manager::release_files_impl() @@ -1200,7 +1198,7 @@ namespace libtorrent int piece_manager::slot_for_piece(int piece_index) const { - assert(piece_index >= 0 && piece_index < m_info.num_pieces()); + assert(piece_index >= 0 && piece_index < m_info->num_pieces()); return m_piece_to_slot[piece_index]; } @@ -1211,13 +1209,13 @@ namespace libtorrent try { assert(slot_index >= 0); - assert(slot_index < m_info.num_pieces()); + assert(slot_index < m_info->num_pieces()); assert(block_size > 0); adler32_crc crc; std::vector buf(block_size); - int num_blocks = static_cast(m_info.piece_size(slot_index)) / block_size; - int last_block_size = static_cast(m_info.piece_size(slot_index)) % block_size; + int num_blocks = static_cast(m_info->piece_size(slot_index)) / block_size; + int last_block_size = static_cast(m_info->piece_size(slot_index)) % block_size; if (last_block_size == 0) last_block_size = block_size; for (int i = 0; i < num_blocks-1; ++i) @@ -1310,11 +1308,11 @@ namespace libtorrent { // INVARIANT_CHECK; - assert((int)have_pieces.size() == m_info.num_pieces()); + assert((int)have_pieces.size() == m_info->num_pieces()); - const int piece_size = static_cast(m_info.piece_length()); - const int last_piece_size = static_cast(m_info.piece_size( - m_info.num_pieces() - 1)); + const int piece_size = static_cast(m_info->piece_length()); + const int last_piece_size = static_cast(m_info->piece_size( + m_info->num_pieces() - 1)); assert((int)piece_data.size() >= last_piece_size); @@ -1470,7 +1468,7 @@ namespace libtorrent INVARIANT_CHECK; - assert(m_info.piece_length() > 0); + assert(m_info->piece_length() > 0); m_compact_mode = compact_mode; @@ -1480,13 +1478,13 @@ namespace libtorrent // by check_pieces. // m_storage->shuffle(); - m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot); - m_slot_to_piece.resize(m_info.num_pieces(), unallocated); + m_piece_to_slot.resize(m_info->num_pieces(), has_no_slot); + m_slot_to_piece.resize(m_info->num_pieces(), unallocated); m_free_slots.clear(); m_unallocated_slots.clear(); pieces.clear(); - pieces.resize(m_info.num_pieces(), false); + pieces.resize(m_info->num_pieces(), false); num_pieces = 0; // if we have fast-resume info @@ -1591,7 +1589,7 @@ namespace libtorrent return std::make_pair(false, 1.f); } - if (int(m_unallocated_slots.size()) == m_info.num_pieces() + if (int(m_unallocated_slots.size()) == m_info->num_pieces() && !m_fill_mode) { // if there is not a single file on disk, just @@ -1633,8 +1631,8 @@ namespace libtorrent assert(!m_fill_mode); std::vector().swap(m_unallocated_slots); std::fill(m_slot_to_piece.begin(), m_slot_to_piece.end(), int(unassigned)); - m_free_slots.resize(m_info.num_pieces()); - for (int i = 0; i < m_info.num_pieces(); ++i) + m_free_slots.resize(m_info->num_pieces()); + for (int i = 0; i < m_info->num_pieces(); ++i) m_free_slots[i] = i; } @@ -1654,15 +1652,15 @@ namespace libtorrent if (m_hash_to_piece.empty()) { m_current_slot = 0; - for (int i = 0; i < m_info.num_pieces(); ++i) + for (int i = 0; i < m_info->num_pieces(); ++i) { - m_hash_to_piece.insert(std::make_pair(m_info.hash_for_piece(i), i)); + m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i)); } std::fill(pieces.begin(), pieces.end(), false); } - m_piece_data.resize(int(m_info.piece_length())); - int piece_size = int(m_info.piece_size(m_current_slot)); + m_piece_data.resize(int(m_info->piece_length())); + int piece_size = int(m_info->piece_size(m_current_slot)); int num_read = m_storage->read(&m_piece_data[0] , m_current_slot, 0, piece_size); @@ -1865,9 +1863,9 @@ namespace libtorrent { // find the file that failed, and skip all the blocks in that file size_type file_offset = 0; - size_type current_offset = m_current_slot * m_info.piece_length(); - for (torrent_info::file_iterator i = m_info.begin_files(true); - i != m_info.end_files(true); ++i) + size_type current_offset = m_current_slot * m_info->piece_length(); + for (torrent_info::file_iterator i = m_info->begin_files(true); + i != m_info->end_files(true); ++i) { file_offset += i->size; if (file_offset > current_offset) break; @@ -1875,8 +1873,8 @@ namespace libtorrent assert(file_offset > current_offset); int skip_blocks = static_cast( - (file_offset - current_offset + m_info.piece_length() - 1) - / m_info.piece_length()); + (file_offset - current_offset + m_info->piece_length() - 1) + / m_info->piece_length()); for (int i = m_current_slot; i < m_current_slot + skip_blocks; ++i) { @@ -1889,9 +1887,9 @@ namespace libtorrent } ++m_current_slot; - if (m_current_slot >= m_info.num_pieces()) + if (m_current_slot >= m_info->num_pieces()) { - assert(m_current_slot == m_info.num_pieces()); + assert(m_current_slot == m_info->num_pieces()); // clear the memory we've been using std::vector().swap(m_piece_data); @@ -1903,7 +1901,7 @@ namespace libtorrent assert(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - return std::make_pair(false, (float)m_current_slot / m_info.num_pieces()); + return std::make_pair(false, (float)m_current_slot / m_info->num_pieces()); } int piece_manager::allocate_slot_for_piece(int piece_index) @@ -1945,7 +1943,7 @@ namespace libtorrent // special case to make sure we don't use the last slot // when we shouldn't, since it's smaller than ordinary slots - if (*iter == m_info.num_pieces() - 1 && piece_index != *iter) + if (*iter == m_info->num_pieces() - 1 && piece_index != *iter) { if (m_free_slots.size() == 1) allocate_slots(1); @@ -2050,7 +2048,7 @@ namespace libtorrent } else if (m_fill_mode) { - int piece_size = int(m_info.piece_size(pos)); + int piece_size = int(m_info->piece_size(pos)); int offset = 0; for (; piece_size > 0; piece_size -= stack_buffer_size , offset += stack_buffer_size) @@ -2076,8 +2074,8 @@ namespace libtorrent boost::recursive_mutex::scoped_lock lock(m_mutex); if (m_piece_to_slot.empty()) return; - assert((int)m_piece_to_slot.size() == m_info.num_pieces()); - assert((int)m_slot_to_piece.size() == m_info.num_pieces()); + assert((int)m_piece_to_slot.size() == m_info->num_pieces()); + assert((int)m_slot_to_piece.size() == m_info->num_pieces()); for (std::vector::const_iterator i = m_free_slots.begin(); i != m_free_slots.end(); ++i) @@ -2099,7 +2097,7 @@ namespace libtorrent == m_unallocated_slots.end()); } - for (int i = 0; i < m_info.num_pieces(); ++i) + for (int i = 0; i < m_info->num_pieces(); ++i) { // Check domain of piece_to_slot's elements if (m_piece_to_slot[i] != has_no_slot) @@ -2187,7 +2185,7 @@ namespace libtorrent s << "index\tslot\tpiece\n"; - for (int i = 0; i < m_info.num_pieces(); ++i) + for (int i = 0; i < m_info->num_pieces(); ++i) { s << i << "\t" << m_slot_to_piece[i] << "\t"; s << m_piece_to_slot[i] << "\n"; diff --git a/src/torrent.cpp b/src/torrent.cpp index 9cd2c277c..1a3083b7d 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -150,7 +150,7 @@ namespace libtorrent torrent::torrent( session_impl& ses , aux::checker_impl& checker - , torrent_info const& tf + , boost::intrusive_ptr tf , fs::path const& save_path , tcp::endpoint const& net_interface , bool compact_mode @@ -181,7 +181,7 @@ namespace libtorrent , m_ses(ses) , m_checker(checker) , m_picker(0) - , m_trackers(m_torrent_file.trackers()) + , m_trackers(m_torrent_file->trackers()) , m_last_working_tracker(-1) , m_currently_trying_tracker(0) , m_failed_trackers(0) @@ -221,7 +221,7 @@ namespace libtorrent , int block_size , storage_constructor_type sc , bool paused) - : m_torrent_file(info_hash) + : m_torrent_file(new torrent_info(info_hash)) , m_abort(false) , m_paused(paused) , m_just_paused(false) @@ -277,7 +277,7 @@ namespace libtorrent if (tracker_url) { m_trackers.push_back(announce_entry(tracker_url)); - m_torrent_file.add_tracker(tracker_url); + m_torrent_file->add_tracker(tracker_url); } m_policy.reset(new policy(this)); @@ -286,7 +286,7 @@ namespace libtorrent void torrent::start() { boost::weak_ptr self(shared_from_this()); - if (m_torrent_file.is_valid()) init(); + if (m_torrent_file->is_valid()) init(); m_announce_timer.expires_from_now(seconds(1)); m_announce_timer.async_wait(m_ses.m_strand.wrap( bind(&torrent::on_announce_disp, self, _1))); @@ -296,7 +296,7 @@ namespace libtorrent bool torrent::should_announce_dht() const { // don't announce private torrents - if (m_torrent_file.is_valid() && m_torrent_file.priv()) return false; + if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; if (m_trackers.empty()) return true; @@ -334,7 +334,7 @@ namespace libtorrent std::string torrent::name() const { - if (valid_metadata()) return m_torrent_file.name(); + if (valid_metadata()) return m_torrent_file->name(); if (m_name) return *m_name; return ""; } @@ -350,22 +350,22 @@ namespace libtorrent // shared_from_this() void torrent::init() { - assert(m_torrent_file.is_valid()); - assert(m_torrent_file.num_files() > 0); - assert(m_torrent_file.total_size() >= 0); + assert(m_torrent_file->is_valid()); + assert(m_torrent_file->num_files() > 0); + assert(m_torrent_file->total_size() >= 0); - m_have_pieces.resize(m_torrent_file.num_pieces(), false); + m_have_pieces.resize(m_torrent_file->num_pieces(), false); // the shared_from_this() will create an intentional // cycle of ownership, se the hpp file for description. m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor); m_storage = m_owning_storage.get(); - 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(m_torrent_file.piece_length() / m_block_size) - , static_cast((m_torrent_file.total_size()+m_block_size-1)/m_block_size))); + static_cast(m_torrent_file->piece_length() / m_block_size) + , static_cast((m_torrent_file->total_size()+m_block_size-1)/m_block_size))); - std::vector const& url_seeds = m_torrent_file.url_seeds(); + std::vector const& url_seeds = m_torrent_file->url_seeds(); std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds , m_web_seeds.begin())); } @@ -393,7 +393,7 @@ namespace libtorrent { boost::weak_ptr self(shared_from_this()); - if (!m_torrent_file.priv()) + if (!m_torrent_file->priv()) { // announce on local network every 5 minutes m_announce_timer.expires_from_now(minutes(5)); @@ -401,7 +401,7 @@ namespace libtorrent bind(&torrent::on_announce_disp, self, _1))); // announce with the local discovery service - m_ses.announce_lsd(m_torrent_file.info_hash()); + m_ses.announce_lsd(m_torrent_file->info_hash()); } else { @@ -419,7 +419,7 @@ namespace libtorrent // TODO: There should be a way to abort an announce operation on the dht. // when the torrent is destructed assert(m_ses.m_external_listen_port > 0); - m_ses.m_dht->announce(m_torrent_file.info_hash() + m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.m_external_listen_port , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); } @@ -465,7 +465,7 @@ namespace libtorrent { INVARIANT_CHECK; - if (m_torrent_file.trackers().empty()) return false; + if (m_torrent_file->trackers().empty()) return false; if (m_just_paused) { @@ -615,7 +615,7 @@ namespace libtorrent // if we don't have the metadata yet, we // cannot tell how big the torrent is. if (!valid_metadata()) return -1; - return m_torrent_file.total_size() + return m_torrent_file->total_size() - quantized_bytes_done(); } @@ -625,23 +625,23 @@ namespace libtorrent if (!valid_metadata()) return 0; - if (m_torrent_file.num_pieces() == 0) + if (m_torrent_file->num_pieces() == 0) return 0; - if (is_seed()) return m_torrent_file.total_size(); + if (is_seed()) return m_torrent_file->total_size(); - const int last_piece = m_torrent_file.num_pieces() - 1; + const int last_piece = m_torrent_file->num_pieces() - 1; size_type total_done - = m_num_pieces * m_torrent_file.piece_length(); + = m_num_pieces * m_torrent_file->piece_length(); // if we have the last piece, we have to correct // the amount we have, since the first calculation // assumed all pieces were of equal size if (m_have_pieces[last_piece]) { - int corr = m_torrent_file.piece_size(last_piece) - - m_torrent_file.piece_length(); + int corr = m_torrent_file->piece_size(last_piece) + - m_torrent_file->piece_length(); total_done += corr; } return total_done; @@ -654,42 +654,42 @@ namespace libtorrent { INVARIANT_CHECK; - if (!valid_metadata() || m_torrent_file.num_pieces() == 0) + if (!valid_metadata() || m_torrent_file->num_pieces() == 0) return tuple(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()) - return make_tuple(m_torrent_file.total_size() - , m_torrent_file.total_size()); + 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(); + * m_torrent_file->piece_length(); size_type total_done - = m_num_pieces * m_torrent_file.piece_length(); - assert(m_num_pieces < m_torrent_file.num_pieces()); + = m_num_pieces * m_torrent_file->piece_length(); + assert(m_num_pieces < m_torrent_file->num_pieces()); // if we have the last piece, we have to correct // the amount we have, since the first calculation // assumed all pieces were of equal size if (m_have_pieces[last_piece]) { - int corr = m_torrent_file.piece_size(last_piece) - - m_torrent_file.piece_length(); + int corr = m_torrent_file->piece_size(last_piece) + - m_torrent_file->piece_length(); total_done += corr; if (m_picker->piece_priority(last_piece) != 0) wanted_done += corr; } - assert(total_done <= m_torrent_file.total_size()); - assert(wanted_done <= m_torrent_file.total_size()); + assert(total_done <= m_torrent_file->total_size()); + assert(wanted_done <= m_torrent_file->total_size()); const std::vector& dl_queue = m_picker->get_download_queue(); const int blocks_per_piece = static_cast( - m_torrent_file.piece_length() / m_block_size); + m_torrent_file->piece_length() / m_block_size); for (std::vector::const_iterator i = dl_queue.begin(); i != dl_queue.end(); ++i) @@ -722,15 +722,15 @@ namespace libtorrent == piece_picker::block_info::state_finished) { corr -= m_block_size; - corr += m_torrent_file.piece_size(last_piece) % m_block_size; + corr += m_torrent_file->piece_size(last_piece) % m_block_size; } total_done += corr; if (m_picker->piece_priority(index) != 0) wanted_done += corr; } - assert(total_done <= m_torrent_file.total_size()); - assert(wanted_done <= m_torrent_file.total_size()); + assert(total_done <= m_torrent_file->total_size()); + assert(wanted_done <= m_torrent_file->total_size()); std::map downloading_piece; for (const_peer_iterator i = begin(); i != end(); ++i) @@ -760,10 +760,10 @@ namespace libtorrent } #ifndef NDEBUG assert(p->bytes_downloaded <= p->full_block_bytes); - int last_piece = m_torrent_file.num_pieces() - 1; + int last_piece = m_torrent_file->num_pieces() - 1; if (p->piece_index == last_piece - && p->block_index == m_torrent_file.piece_size(last_piece) / block_size()) - assert(p->full_block_bytes == m_torrent_file.piece_size(last_piece) % block_size()); + && p->block_index == m_torrent_file->piece_size(last_piece) / block_size()) + assert(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size()); else assert(p->full_block_bytes == block_size()); #endif @@ -779,7 +779,7 @@ namespace libtorrent #ifndef NDEBUG - if (total_done >= m_torrent_file.total_size()) + if (total_done >= m_torrent_file->total_size()) { std::copy(m_have_pieces.begin(), m_have_pieces.end() , std::ostream_iterator(std::cerr, " ")); @@ -810,8 +810,8 @@ namespace libtorrent } - assert(total_done <= m_torrent_file.total_size()); - assert(wanted_done <= m_torrent_file.total_size()); + assert(total_done <= m_torrent_file->total_size()); + assert(wanted_done <= m_torrent_file->total_size()); #endif @@ -908,14 +908,14 @@ namespace libtorrent // think that it has received all of it until this function // resets the download queue. So, we cannot do the // invariant check here since it assumes: - // (total_done == m_torrent_file.total_size()) => is_seed() + // (total_done == m_torrent_file->total_size()) => is_seed() // INVARIANT_CHECK; assert(m_storage); assert(m_storage->refcount() > 0); assert(m_picker.get()); assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); if (m_ses.m_alerts.should_post(alert::info)) { @@ -924,7 +924,7 @@ namespace libtorrent m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index, s.str())); } // increase the total amount of failed bytes - m_total_failed_bytes += m_torrent_file.piece_size(index); + m_total_failed_bytes += m_torrent_file->piece_size(index); std::vector downloaders; m_picker->get_downloaders(downloaders, index); @@ -1047,7 +1047,7 @@ namespace libtorrent // INVARIANT_CHECK; assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); std::vector downloaders; m_picker->get_downloaders(downloaders, index); @@ -1090,7 +1090,7 @@ namespace libtorrent if (is_seed()) { m_picker.reset(); - m_torrent_file.seed_free(); + m_torrent_file->seed_free(); } } @@ -1124,7 +1124,7 @@ namespace libtorrent // this call is only valid on torrents with metadata assert(m_picker.get()); assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); bool filter_updated = m_picker->set_piece_priority(index, priority); if (filter_updated) update_peer_interest(); @@ -1140,7 +1140,7 @@ namespace libtorrent // this call is only valid on torrents with metadata assert(m_picker.get()); assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); return m_picker->piece_priority(index); } @@ -1176,7 +1176,7 @@ namespace libtorrent if (is_seed()) { pieces.clear(); - pieces.resize(m_torrent_file.num_pieces(), 1); + pieces.resize(m_torrent_file->num_pieces(), 1); return; } @@ -1201,20 +1201,20 @@ namespace libtorrent // the bitmask need to have exactly one bit for every file // in the torrent - assert(int(files.size()) == m_torrent_file.num_files()); + assert(int(files.size()) == m_torrent_file->num_files()); size_type position = 0; - if (m_torrent_file.num_pieces() == 0) return; + if (m_torrent_file->num_pieces() == 0) return; - int piece_length = m_torrent_file.piece_length(); + int piece_length = m_torrent_file->piece_length(); // initialize the piece priorities to 0, then only allow // setting higher priorities - std::vector pieces(m_torrent_file.num_pieces(), 0); + std::vector pieces(m_torrent_file->num_pieces(), 0); for (int i = 0; i < int(files.size()); ++i) { size_type start = position; - size_type size = m_torrent_file.file_at(i).size; + size_type size = m_torrent_file->file_at(i).size; if (size == 0) continue; position += size; // mark all pieces of the file with this file's priority @@ -1250,7 +1250,7 @@ namespace libtorrent // this call is only valid on torrents with metadata assert(m_picker.get()); assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); m_picker->set_piece_priority(index, filter ? 1 : 0); update_peer_interest(); @@ -1287,7 +1287,7 @@ namespace libtorrent assert(m_picker.get()); assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); + assert(index < m_torrent_file->num_pieces()); return m_picker->piece_priority(index) == 0; } @@ -1301,7 +1301,7 @@ namespace libtorrent if (is_seed()) { bitmask.clear(); - bitmask.resize(m_torrent_file.num_pieces(), false); + bitmask.resize(m_torrent_file->num_pieces(), false); return; } @@ -1318,20 +1318,20 @@ namespace libtorrent // the bitmask need to have exactly one bit for every file // in the torrent - assert((int)bitmask.size() == m_torrent_file.num_files()); + assert((int)bitmask.size() == m_torrent_file->num_files()); size_type position = 0; - if (m_torrent_file.num_pieces()) + if (m_torrent_file->num_pieces()) { - int piece_length = m_torrent_file.piece_length(); + int piece_length = m_torrent_file->piece_length(); // mark all pieces as filtered, then clear the bits for files // that should be downloaded - std::vector piece_filter(m_torrent_file.num_pieces(), true); + std::vector piece_filter(m_torrent_file->num_pieces(), true); for (int i = 0; i < (int)bitmask.size(); ++i) { size_type start = position; - position += m_torrent_file.file_at(i).size; + position += m_torrent_file->file_at(i).size; // is the file selected for download? if (!bitmask[i]) { @@ -1366,7 +1366,7 @@ namespace libtorrent m_next_request = time_now() + seconds(tracker_retry_delay_max); tracker_request req; - req.info_hash = m_torrent_file.info_hash(); + req.info_hash = m_torrent_file->info_hash(); req.pid = m_ses.get_peer_id(); req.downloaded = m_stat.total_payload_download(); req.uploaded = m_stat.total_payload_upload(); @@ -1890,8 +1890,8 @@ namespace libtorrent { INVARIANT_CHECK; - assert(!m_torrent_file.is_valid()); - m_torrent_file.parse_info_section(metadata); + assert(!m_torrent_file->is_valid()); + m_torrent_file->parse_info_section(metadata); init(); @@ -1901,12 +1901,12 @@ namespace libtorrent new aux::piece_checker_data); d->torrent_ptr = shared_from_this(); d->save_path = m_save_path; - d->info_hash = m_torrent_file.info_hash(); + d->info_hash = m_torrent_file->info_hash(); // add the torrent to the queue to be checked m_checker.m_torrents.push_back(d); typedef session_impl::torrent_map torrent_map; torrent_map::iterator i = m_ses.m_torrents.find( - m_torrent_file.info_hash()); + m_torrent_file->info_hash()); assert(i != m_ses.m_torrents.end()); m_ses.m_torrents.erase(i); // and notify the thread that it got another @@ -2291,7 +2291,7 @@ namespace libtorrent if (is_seed()) { m_picker.reset(); - m_torrent_file.seed_free(); + m_torrent_file->seed_free(); } if (!m_connections_initialized) @@ -2374,7 +2374,7 @@ namespace libtorrent torrent_handle torrent::get_handle() const { - return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash()); + return torrent_handle(&m_ses, &m_checker, m_torrent_file->info_hash()); } session_settings const& torrent::settings() const @@ -2417,7 +2417,7 @@ namespace libtorrent if (valid_metadata()) { - assert(m_abort || int(m_have_pieces.size()) == m_torrent_file.num_pieces()); + assert(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces()); } else { @@ -2425,12 +2425,12 @@ namespace libtorrent } size_type total_done = quantized_bytes_done(); - if (m_torrent_file.is_valid()) + if (m_torrent_file->is_valid()) { if (is_seed()) - assert(total_done == m_torrent_file.total_size()); + assert(total_done == m_torrent_file->total_size()); else - assert(total_done != m_torrent_file.total_size()); + assert(total_done != m_torrent_file->total_size()); } else { @@ -2441,7 +2441,7 @@ namespace libtorrent assert(m_num_pieces == std::count(m_have_pieces.begin(), m_have_pieces.end(), true)); assert(!valid_metadata() || m_block_size > 0); - assert(!valid_metadata() || (m_torrent_file.piece_length() % 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 @@ -2678,7 +2678,7 @@ namespace libtorrent assert(m_storage); assert(m_storage->refcount() > 0); assert(piece_index >= 0); - assert(piece_index < m_torrent_file.num_pieces()); + assert(piece_index < m_torrent_file->num_pieces()); assert(piece_index < (int)m_have_pieces.size()); m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified @@ -2690,7 +2690,7 @@ namespace libtorrent { sha1_hash h(j.str); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - f(m_torrent_file.hash_for_piece(j.piece) == h); + f(m_torrent_file->hash_for_piece(j.piece) == h); } const tcp::endpoint& torrent::current_tracker() const @@ -2706,12 +2706,12 @@ namespace libtorrent assert(valid_metadata()); fp.clear(); - fp.resize(m_torrent_file.num_files(), 0.f); + fp.resize(m_torrent_file->num_files(), 0.f); - for (int i = 0; i < m_torrent_file.num_files(); ++i) + for (int i = 0; i < m_torrent_file->num_files(); ++i) { - peer_request ret = m_torrent_file.map_file(i, 0, 0); - size_type size = m_torrent_file.file_at(i).size; + peer_request ret = m_torrent_file->map_file(i, 0, 0); + size_type size = m_torrent_file->file_at(i).size; // zero sized files are considered // 100% done all the time @@ -2724,7 +2724,7 @@ namespace libtorrent size_type done = 0; while (size > 0) { - size_type bytes_step = (std::min)(m_torrent_file.piece_size(ret.piece) + size_type bytes_step = (std::min)(m_torrent_file->piece_size(ret.piece) - ret.start, size); if (m_have_pieces[ret.piece]) done += bytes_step; ++ret.piece; @@ -2733,7 +2733,7 @@ namespace libtorrent } assert(size == 0); - fp[i] = static_cast(done) / m_torrent_file.file_at(i).size; + fp[i] = static_cast(done) / m_torrent_file->file_at(i).size; } } @@ -2820,21 +2820,21 @@ namespace libtorrent // fill in status that depends on metadata - st.total_wanted = m_torrent_file.total_size(); + st.total_wanted = m_torrent_file->total_size(); if (m_picker.get() && (m_picker->num_filtered() > 0 || m_picker->num_have_filtered() > 0)) { int filtered_pieces = m_picker->num_filtered() + m_picker->num_have_filtered(); - int last_piece_index = m_torrent_file.num_pieces() - 1; + int last_piece_index = m_torrent_file->num_pieces() - 1; if (m_picker->piece_priority(last_piece_index) == 0) { - st.total_wanted -= m_torrent_file.piece_size(last_piece_index); + st.total_wanted -= m_torrent_file->piece_size(last_piece_index); --filtered_pieces; } - st.total_wanted -= filtered_pieces * m_torrent_file.piece_length(); + st.total_wanted -= filtered_pieces * m_torrent_file->piece_length(); } assert(st.total_wanted >= st.total_wanted_done); @@ -2852,7 +2852,7 @@ namespace libtorrent } else if (is_seed()) { - assert(st.total_done == m_torrent_file.total_size()); + assert(st.total_done == m_torrent_file->total_size()); st.state = torrent_status::seeding; } else if (st.total_wanted_done == st.total_wanted) diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 1c672bdfe..5f9f0deca 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -23,7 +23,7 @@ void on_read_piece(int ret, disk_io_job const& j, char const* data, int size) TEST_CHECK(std::equal(j.buffer, j.buffer + ret, data)); } -void run_storage_tests(torrent_info& info, bool compact_allocation = true) +void run_storage_tests(boost::intrusive_ptr info, bool compact_allocation = true) { const int half = piece_size / 2; @@ -39,16 +39,16 @@ void run_storage_tests(torrent_info& info, bool compact_allocation = true) { 0, 0, 1, 0, 0, 0, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1}; - info.set_hash(0, hasher(piece0, piece_size).final()); - info.set_hash(1, hasher(piece1, piece_size).final()); - info.set_hash(2, hasher(piece2, piece_size).final()); + info->set_hash(0, hasher(piece0, piece_size).final()); + info->set_hash(1, hasher(piece1, piece_size).final()); + info->set_hash(2, hasher(piece2, piece_size).final()); - info.create_torrent(); + info->create_torrent(); create_directory(initial_path() / "temp_storage"); int num_pieces = (1 + 612 + 17 + piece_size - 1) / piece_size; - TEST_CHECK(info.num_pieces() == num_pieces); + TEST_CHECK(info->num_pieces() == num_pieces); char piece[piece_size]; @@ -131,13 +131,13 @@ void run_storage_tests(torrent_info& info, bool compact_allocation = true) int test_main() { - torrent_info info; - info.set_piece_size(piece_size); - info.add_file("temp_storage/test1.tmp", 17); - info.add_file("temp_storage/test2.tmp", 612); - info.add_file("temp_storage/test3.tmp", 0); - info.add_file("temp_storage/test4.tmp", 0); - info.add_file("temp_storage/test5.tmp", 1); + boost::intrusive_ptr info(new torrent_info()); + info->set_piece_size(piece_size); + info->add_file("temp_storage/test1.tmp", 17); + info->add_file("temp_storage/test2.tmp", 612); + info->add_file("temp_storage/test3.tmp", 0); + info->add_file("temp_storage/test4.tmp", 0); + info->add_file("temp_storage/test5.tmp", 1); run_storage_tests(info); @@ -155,7 +155,7 @@ int test_main() // make sure remap_files works std::vector > map; map.push_back(std::make_pair(std::string("temp_storage/test.tmp"), 17 + 612 + 1)); - bool ret = info.remap_files(map); + bool ret = info->remap_files(map); TEST_CHECK(ret); run_storage_tests(info, false); @@ -167,9 +167,9 @@ int test_main() // ============================================== - info = torrent_info(); - info.set_piece_size(piece_size); - info.add_file("temp_storage/test1.tmp", 17 + 612 + 1); + info = new torrent_info(); + info->set_piece_size(piece_size); + info->add_file("temp_storage/test1.tmp", 17 + 612 + 1); run_storage_tests(info); diff --git a/test/test_web_seed.cpp b/test/test_web_seed.cpp index 4b981e50c..4ae5f278a 100644 --- a/test/test_web_seed.cpp +++ b/test/test_web_seed.cpp @@ -37,27 +37,27 @@ void test_transfer() { using namespace libtorrent; - torrent_info torrent_file; - torrent_file.add_url_seed("http://127.0.0.1/bravia_paint_ad_70sec_1280x720.mov"); + boost::intrusive_ptr torrent_file(new torrent_info); + torrent_file->add_url_seed("http://127.0.0.1/bravia_paint_ad_70sec_1280x720.mov"); path full_path = "/Library/WebServer/Documents/bravia_paint_ad_70sec_1280x720.mov"; - add_files(torrent_file, full_path.branch_path(), full_path.leaf()); + add_files(*torrent_file, full_path.branch_path(), full_path.leaf()); file_pool fp; boost::scoped_ptr s(default_storage_constructor( torrent_file, full_path.branch_path(), fp)); // calculate the hash for all pieces - int num = torrent_file.num_pieces(); - std::vector buf(torrent_file.piece_length()); + int num = torrent_file->num_pieces(); + std::vector buf(torrent_file->piece_length()); for (int i = 0; i < num; ++i) { - s->read(&buf[0], i, 0, torrent_file.piece_size(i)); - hasher h(&buf[0], torrent_file.piece_size(i)); - torrent_file.set_hash(i, h.final()); + s->read(&buf[0], i, 0, torrent_file->piece_size(i)); + hasher h(&buf[0], torrent_file->piece_size(i)); + torrent_file->set_hash(i, h.final()); } // to calculate the info_hash - entry te = torrent_file.create_torrent(); + entry te = torrent_file->create_torrent(); te.print(std::cout); // std::ofstream torrent("web_seed.torrent", std::ios::binary | std::ios::trunc);