From a5847956e1477579b6bd60f0ba05bb072b10df76 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 9 May 2007 22:54:26 +0000 Subject: [PATCH] most of the metadata is now freed when a torrent becomes a seed. #44 --- include/libtorrent/torrent_handle.hpp | 1 + include/libtorrent/torrent_info.hpp | 26 +++++++++++++-- src/metadata_transfer.cpp | 18 ++++++++++- src/torrent.cpp | 26 +++++++++------ src/torrent_info.cpp | 46 ++++++++++++++++++++------- 5 files changed, 91 insertions(+), 26 deletions(-) diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index bd22f0e9b..cb4b892d2 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -373,3 +373,4 @@ namespace libtorrent } #endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED + diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index cac8544a2..d26f9f1f2 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -115,7 +115,11 @@ namespace libtorrent std::vector map_block(int piece, size_type offset, int size) const; peer_request map_file(int file, size_type offset, int size) const; - std::vector const& url_seeds() const { return m_url_seeds; } + std::vector const& url_seeds() const + { + assert(!m_half_metadata); + return m_url_seeds; + } typedef std::vector::const_iterator file_iterator; typedef std::vector::const_reverse_iterator reverse_file_iterator; @@ -135,7 +139,7 @@ namespace libtorrent size_type total_size() const { assert(m_piece_length > 0); return m_total_size; } size_type piece_length() const { assert(m_piece_length > 0); return m_piece_length; } - int num_pieces() const { assert(m_piece_length > 0); return (int)m_piece_hash.size(); } + int num_pieces() const { assert(m_piece_length > 0); return m_num_pieces; } const sha1_hash& info_hash() const { return m_info_hash; } const std::string& name() const { assert(m_piece_length > 0); return m_name; } @@ -156,6 +160,7 @@ namespace libtorrent { assert(index >= 0); assert(index < (int)m_piece_hash.size()); + assert(!m_half_metadata); return m_piece_hash[index]; } @@ -171,7 +176,10 @@ namespace libtorrent typedef std::vector > nodes_t; nodes_t const& nodes() const - { return m_nodes; } + { + assert(!m_half_metadata); + return m_nodes; + } void add_node(std::pair const& node); @@ -180,6 +188,10 @@ namespace libtorrent entry extra(char const* key) const { return m_extra_info[key]; } + // frees parts of the metadata that isn't + // used by seeds + void seed_free(); + private: void read_torrent_info(const entry& libtorrent); @@ -205,6 +217,9 @@ namespace libtorrent // the sum of all filesizes size_type m_total_size; + // the number of pieces in the torrent + int m_num_pieces; + // the hash that identifies this torrent // is mutable because it's calculated // lazily @@ -241,6 +256,11 @@ namespace libtorrent // reproduce the info-section when sending the metadata // to peers. entry m_extra_info; + +#ifndef NDEBUG + // this is set to true when seed_free() is called + bool m_half_metadata; +#endif }; } diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index 42a5d2a03..fe308f926 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -106,7 +106,15 @@ namespace libtorrent { namespace { m_requested_metadata.resize(256, 0); } - + + virtual void on_files_checked() + { + // if the torrent is a seed, copy the metadata from + // the torrent before it is deallocated + if (m_torrent.is_seed()) + metadata(); + } + virtual boost::shared_ptr new_connection( peer_connection* pc); @@ -211,6 +219,14 @@ namespace libtorrent { namespace m_metadata_size = total_size; } + void piece_pass(int) + { + // if we became a seed, copy the metadata from + // the torrent before it is deallocated + if (m_torrent.is_seed()) + metadata(); + } + private: torrent& m_torrent; diff --git a/src/torrent.cpp b/src/torrent.cpp index d99fccc9d..36650eb4f 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1010,7 +1010,11 @@ namespace libtorrent try { (*i)->on_piece_pass(index); } catch (std::exception&) {} } #endif - if (is_seed()) m_picker.reset(); + if (is_seed()) + { + m_picker.reset(); + m_torrent_file.seed_free(); + } } std::string torrent::tracker_login() const @@ -2108,9 +2112,19 @@ namespace libtorrent if (m_sequenced_download_threshold > 0) picker().set_sequenced_download_threshold(m_sequenced_download_threshold); } - else + +#ifndef TORRENT_DISABLE_EXTENSIONS + for (extension_list_t::iterator i = m_extensions.begin() + , end(m_extensions.end()); i != end; ++i) + { + try { (*i)->on_files_checked(); } catch (std::exception&) {} + } +#endif + + if (is_seed()) { m_picker.reset(); + m_torrent_file.seed_free(); } if (!m_connections_initialized) @@ -2142,14 +2156,6 @@ namespace libtorrent #ifndef NDEBUG m_initial_done = boost::get<0>(bytes_done()); #endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_files_checked(); } catch (std::exception&) {} - } -#endif } alert_manager& torrent::alerts() const diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 4083a24ca..e546a1243 100755 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -219,10 +219,14 @@ namespace libtorrent // standard constructor that parses a torrent file torrent_info::torrent_info(const entry& torrent_file) - : m_creation_date(pt::ptime(pt::not_a_date_time)) + : m_num_pieces(0) + , m_creation_date(pt::ptime(pt::not_a_date_time)) , m_multifile(false) , m_private(false) , m_extra_info(entry::dictionary_t) +#ifndef NDEBUG + , m_half_metadata(false) +#endif { try { @@ -241,24 +245,32 @@ namespace libtorrent torrent_info::torrent_info(sha1_hash const& info_hash) : m_piece_length(0) , m_total_size(0) + , m_num_pieces(0) , m_info_hash(info_hash) , m_name() , m_creation_date(pt::second_clock::universal_time()) , m_multifile(false) , m_private(false) , m_extra_info(entry::dictionary_t) +#ifndef NDEBUG + , m_half_metadata(false) +#endif { } torrent_info::torrent_info() : m_piece_length(0) , m_total_size(0) + , m_num_pieces(0) , m_info_hash(0) , m_name() , m_creation_date(pt::second_clock::universal_time()) , m_multifile(false) , m_private(false) , m_extra_info(entry::dictionary_t) +#ifndef NDEBUG + , m_half_metadata(false) +#endif { } @@ -278,15 +290,15 @@ namespace libtorrent } } #endif + assert(!m_half_metadata); m_piece_length = size; - - int num_pieces = static_cast( + m_num_pieces = static_cast( (m_total_size + m_piece_length - 1) / m_piece_length); int old_num_pieces = static_cast(m_piece_hash.size()); - m_piece_hash.resize(num_pieces); - for (int i = old_num_pieces; i < num_pieces; ++i) + m_piece_hash.resize(m_num_pieces); + for (int i = old_num_pieces; i < m_num_pieces; ++i) { m_piece_hash[i].clear(); } @@ -344,14 +356,14 @@ namespace libtorrent // we want this division to round upwards, that's why we have the // extra addition - int num_pieces = static_cast((m_total_size + m_piece_length - 1) / m_piece_length); - m_piece_hash.resize(num_pieces); + m_num_pieces = static_cast((m_total_size + m_piece_length - 1) / m_piece_length); + m_piece_hash.resize(m_num_pieces); const std::string& hash_string = info["pieces"].string(); - if ((int)hash_string.length() != num_pieces * 20) + if ((int)hash_string.length() != m_num_pieces * 20) throw invalid_torrent_file(); - for (int i = 0; i < num_pieces; ++i) + for (int i = 0; i < m_num_pieces; ++i) std::copy( hash_string.begin() + i*20 , hash_string.begin() + (i+1)*20 @@ -550,12 +562,12 @@ namespace libtorrent if (m_piece_length == 0) m_piece_length = 256 * 1024; - int num_pieces = static_cast( + m_num_pieces = static_cast( (m_total_size + m_piece_length - 1) / m_piece_length); int old_num_pieces = static_cast(m_piece_hash.size()); - m_piece_hash.resize(num_pieces); - if (num_pieces > old_num_pieces) + m_piece_hash.resize(m_num_pieces); + if (m_num_pieces > old_num_pieces) std::for_each(m_piece_hash.begin() + old_num_pieces , m_piece_hash.end(), boost::bind(&sha1_hash::clear, _1)); } @@ -736,6 +748,16 @@ namespace libtorrent assert(false); } + void torrent_info::seed_free() + { + std::vector().swap(m_url_seeds); + nodes_t().swap(m_nodes); + std::vector().swap(m_piece_hash); +#ifndef NDEBUG + m_half_metadata = true; +#endif + } + // ------- start deprecation ------- void torrent_info::print(std::ostream& os) const