From c050b22d8fa648ae839a7d7ef053f45255235f37 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 14 Feb 2010 01:39:55 +0000 Subject: [PATCH] optimized memory usage for torrent objects --- bindings/python/src/session_settings.cpp | 1 + docs/manual.rst | 5 + include/libtorrent/Makefile.am | 1 + include/libtorrent/aux_/session_impl.hpp | 27 ++ include/libtorrent/lazy_entry.hpp | 21 +- include/libtorrent/policy.hpp | 6 +- include/libtorrent/session_settings.hpp | 5 + include/libtorrent/socket.hpp | 2 +- include/libtorrent/stat.hpp | 2 +- include/libtorrent/torrent.hpp | 383 +++++++++--------- include/libtorrent/tracker_manager.hpp | 3 +- src/lazy_bdecode.cpp | 8 +- src/peer_connection.cpp | 12 +- src/policy.cpp | 4 +- src/session_impl.cpp | 69 +++- src/torrent.cpp | 470 +++++++++++------------ src/torrent_handle.cpp | 2 +- src/torrent_info.cpp | 2 +- 18 files changed, 552 insertions(+), 471 deletions(-) diff --git a/bindings/python/src/session_settings.cpp b/bindings/python/src/session_settings.cpp index edd9a06e6..c258b06b8 100644 --- a/bindings/python/src/session_settings.cpp +++ b/bindings/python/src/session_settings.cpp @@ -110,6 +110,7 @@ void bind_session_settings() .def_readwrite("drop_skipped_requests", &session_settings::drop_skipped_requests) .def_readwrite("low_prio_disk", &session_settings::low_prio_disk) .def_readwrite("local_service_announce_interval", &session_settings::local_service_announce_interval) + .def_readwrite("dht_announce_interval", &session_settings::dht_announce_interval) .def_readwrite("udp_tracker_token_expiry", &session_settings::udp_tracker_token_expiry) .def_readwrite("volatile_read_cache", &session_settings::volatile_read_cache) .def_readwrite("guided_read_cache", &session_settings::guided_read_cache) diff --git a/docs/manual.rst b/docs/manual.rst index b42329360..a6497263d 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3759,6 +3759,7 @@ session_settings bool low_prio_disk; int local_service_announce_interval; + int dht_announce_interval; int udp_tracker_token_expiry; bool volatile_read_cache; @@ -4275,6 +4276,10 @@ network announces for a torrent. By default, when local service discovery is enabled a torrent announces itself every 5 minutes. This interval is specified in seconds. +``dht_announce_interval`` is the number of seconds between announcing +torrents to the distributed hash table (DHT). This is specified to +be 15 minutes which is its default. + ``udp_tracker_token_expiry`` is the number of seconds libtorrent will keep UDP tracker connection tokens around for. This is specified to be 60 seconds, and defaults to that. The higher this value is, the diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 825069be9..450211663 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -90,6 +90,7 @@ nobase_include_HEADERS = \ tracker_manager.hpp \ udp_socket.hpp \ udp_tracker_connection.hpp \ + union_endpoint.hpp \ upnp.hpp \ utf8.hpp \ variant_stream.hpp \ diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 48d9fcc73..005449760 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -196,6 +196,8 @@ namespace libtorrent entry dht_state(mutex::scoped_lock& l) const; void maybe_update_udp_mapping(int nat, int local_port, int external_port); + + void on_dht_announce(error_code const& e); #endif #ifndef TORRENT_DISABLE_ENCRYPTION @@ -697,6 +699,10 @@ namespace libtorrent void on_receive_udp(error_code const& e , udp::endpoint const& ep, char const* buf, int len); + + // this announce timer is used + // by the DHT. + deadline_timer m_dht_announce_timer; #endif #ifndef TORRENT_DISABLE_ENCRYPTION @@ -720,10 +726,20 @@ namespace libtorrent // 5 minutes) torrent_map::iterator m_next_lsd_torrent; +#ifndef TORRENT_DISABLE_DHT + // torrents are announced on the DHT in a + // round-robin fashion. All torrents are cycled through + // within the DHT announce interval (which defaults to + // 15 minutes) + torrent_map::iterator m_next_dht_torrent; +#endif + // this announce timer is used // by Local service discovery deadline_timer m_lsd_announce_timer; + tcp::resolver m_host_resolver; + // the index of the torrent that will be offered to // connect to a peer next time on_tick is called. // This implements a round robin. @@ -745,6 +761,17 @@ namespace libtorrent // the number of send buffers that are allocated int m_buffer_allocations; #endif + + // each second tick the timer takes a little + // bit longer than one second to trigger. The + // extra time it took is accumulated into this + // counter. Every time it exceeds 1000, torrents + // will tick their timers 2 seconds instead of one. + // this keeps the timers more accurate over time + // as a kind of "leap second" to adjust for the + // accumulated error + boost::uint16_t m_tick_residual; + #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING boost::shared_ptr create_log(std::string const& name , int instance, bool append = true); diff --git a/include/libtorrent/lazy_entry.hpp b/include/libtorrent/lazy_entry.hpp index 13d54f8b5..4f7f3bd6e 100644 --- a/include/libtorrent/lazy_entry.hpp +++ b/include/libtorrent/lazy_entry.hpp @@ -75,7 +75,7 @@ namespace libtorrent none_t, dict_t, list_t, string_t, int_t }; - lazy_entry() : m_type(none_t), m_begin(0), m_end(0) + lazy_entry() : m_begin(0), m_end(0), m_type(none_t) { m_data.start = 0; } entry_type_t type() const { return m_type; } @@ -179,7 +179,7 @@ namespace libtorrent lazy_entry* list_at(int i) { TORRENT_ASSERT(m_type == list_t); - TORRENT_ASSERT(i < m_size); + TORRENT_ASSERT(i < int(m_size)); return &m_data.list[i]; } lazy_entry const* list_at(int i) const @@ -192,7 +192,7 @@ namespace libtorrent int list_size() const { TORRENT_ASSERT(m_type == list_t); - return m_size; + return int(m_size); } // end points one byte passed last byte @@ -223,17 +223,20 @@ namespace libtorrent void swap(lazy_entry& e) { using std::swap; - swap(m_type, e.m_type); + entry_type_t tmp1 = e.m_type; + e.m_type = m_type; + m_type = tmp1; + boost::uint32_t tmp2 = e.m_capacity; + e.m_capacity = m_capacity; + m_capacity = tmp2; swap(m_data.start, e.m_data.start); swap(m_size, e.m_size); - swap(m_capacity, e.m_capacity); swap(m_begin, e.m_begin); swap(m_end, e.m_end); } private: - entry_type_t m_type; union data_t { lazy_dict_entry* dict; @@ -241,13 +244,15 @@ namespace libtorrent char const* start; } m_data; - int m_size; // if list or dictionary, the number of items - int m_capacity; // if list or dictionary, allocated number of items // used for dictionaries and lists to record the range // in the original buffer they are based on char const* m_begin; char const* m_end; + boost::uint32_t m_size; // if list or dictionary, the number of items + boost::uint32_t m_capacity:29; // if list or dictionary, allocated number of items + entry_type_t m_type:3; + // non-copyable lazy_entry(lazy_entry const&); lazy_entry const& operator=(lazy_entry const&); diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 5623522e0..15a2a45aa 100644 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -435,12 +435,12 @@ namespace libtorrent peers_t m_peers; + torrent* m_torrent; + // since the peer list can grow too large // to scan all of it, start at this iterator int m_round_robin; - torrent* m_torrent; - // The number of peers in our peer list // that are connect candidates. i.e. they're // not already connected and they have not @@ -460,7 +460,7 @@ namespace libtorrent // this state. Every time m_torrent->is_finished() // is different from this state, we need to // recalculate the connect candidates. - bool m_finished; + bool m_finished:1; }; inline policy::ipv4_peer::ipv4_peer( diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index e4803e286..8a9ee7ced 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -191,6 +191,7 @@ namespace libtorrent , drop_skipped_requests(false) , low_prio_disk(true) , local_service_announce_interval(5 * 60) + , dht_announce_interval(15 * 60) , udp_tracker_token_expiry(60) , volatile_read_cache(false) , guided_read_cache(true) @@ -705,6 +706,10 @@ namespace libtorrent // torrents. Defaults to 5 minutes int local_service_announce_interval; + // number of seconds between DHT announces for + // torrents. Defaults to 15 minutes + int dht_announce_interval; + // the number of seconds a connection ID received // from a UDP tracker is valid for. This is specified // as 60 seconds diff --git a/include/libtorrent/socket.hpp b/include/libtorrent/socket.hpp index 598106af6..b3f7c6fb5 100644 --- a/include/libtorrent/socket.hpp +++ b/include/libtorrent/socket.hpp @@ -96,7 +96,7 @@ namespace libtorrent namespace asio = boost::asio; #endif - + #if TORRENT_USE_IPV6 struct v6only { diff --git a/include/libtorrent/stat.hpp b/include/libtorrent/stat.hpp index d839d9392..dcbbcf7fa 100644 --- a/include/libtorrent/stat.hpp +++ b/include/libtorrent/stat.hpp @@ -53,7 +53,7 @@ namespace libtorrent { friend class invariant_access; public: - enum { history = 10 }; + enum { history = 5 }; #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 8f6186401..3745de71c 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bitfield.hpp" #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/deadline_timer.hpp" +#include "libtorrent/union_endpoint.hpp" namespace libtorrent { @@ -99,18 +100,21 @@ namespace libtorrent // http seeds are different from url seeds in the // protocol they use. http seeds follows the original // http seed spec. by John Hoffman - enum type_t { url_seed, http_seed} type; - - bool resolving; - tcp::endpoint endpoint; + enum type_t { url_seed, http_seed } type; + // if this is > now, we can't reconnect yet ptime retry; + // this indicates whether or not we're resolving the + // hostname of this URL + bool resolving; + + tcp::endpoint endpoint; + peer_connection* connection; web_seed_entry(std::string const& url_, type_t type_) - : url(url_), type(type_), resolving(false) - , retry(time_now()), connection(0) {} + : url(url_), type(type_), retry(time_now()), resolving(false), connection(0) {} bool operator==(web_seed_entry const& e) const { return url == e.url && type == e.type; } @@ -195,7 +199,7 @@ namespace libtorrent void read_piece(int piece); void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r, read_piece_struct* rp); - storage_mode_t storage_mode() const { return m_storage_mode; } + storage_mode_t storage_mode() const { return (storage_mode_t)m_storage_mode; } storage_interface* get_storage() { if (!m_owning_storage) return 0; @@ -209,7 +213,7 @@ namespace libtorrent void abort(); bool is_aborted() const { return m_abort; } - torrent_status::state_t state() const { return m_state; } + torrent_status::state_t state() const { return (torrent_status::state_t)m_state; } void set_state(torrent_status::state_t s); session_settings const& settings() const; @@ -294,7 +298,7 @@ namespace libtorrent void file_progress(std::vector& fp, int flags = 0) const; void use_interface(const char* net_interface); - tcp::endpoint const& get_interface() const { return m_net_interface; } + tcp::endpoint get_interface() const { return m_net_interface; } void connect_to_url_seed(std::list::iterator url); bool connect_to_peer(policy::peer* peerinfo); @@ -446,10 +450,10 @@ namespace libtorrent void announce_with_tracker(tracker_request::event_t e = tracker_request::none , address const& bind_interface = address_v4::any()); - ptime const& last_scrape() const { return m_last_scrape; } + int seconds_since_last_scrape() const { return m_last_scrape; } #ifndef TORRENT_DISABLE_DHT - void force_dht_announce(); + void dht_announce(); #endif // sets the username and password that will be sent to @@ -458,7 +462,7 @@ namespace libtorrent // the tcp::endpoint of the tracker that we managed to // announce ourself at the last time we tried to announce - const tcp::endpoint& current_tracker() const; + tcp::endpoint current_tracker() const; announce_entry* find_tracker(tracker_request const& r); @@ -554,7 +558,7 @@ namespace libtorrent #endif } - int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; } + 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); void disconnect_all(error_code const& ec); @@ -781,20 +785,28 @@ namespace libtorrent void queue_torrent_check(); void dequeue_torrent_check(); + void parse_response(const entry& e, std::vector& peer_list); + + void update_tracker_timer(); + + static void on_tracker_announce_disp(boost::weak_ptr p + , error_code const& e); + + void on_tracker_announce(); + +#ifndef TORRENT_DISABLE_DHT + static void on_dht_announce_response_disp(boost::weak_ptr t + , std::vector const& peers); + void on_dht_announce_response(std::vector const& peers); + bool should_announce_dht() const; +#endif + + void remove_time_critical_piece(int piece, bool finished = false); + void remove_time_critical_pieces(std::vector const& priority); + void request_time_critical_pieces(); + policy m_policy; - // total time we've been available on this torrent - // does not count when the torrent is stopped or paused - time_duration m_active_time; - - // total time we've been finished with this torrent - // does not count when the torrent is stopped or paused - time_duration m_finished_time; - - // total time we've been available as a seed on this torrent - // does not count when the torrent is stopped or paused - time_duration m_seeding_time; - // all time totals of uploaded and downloaded payload // stored in resume data size_type m_total_uploaded; @@ -806,17 +818,8 @@ namespace libtorrent // recently was started, to avoid oscillation ptime m_started; - // the last time we initiated a scrape request to - // one of the trackers in this torrent - ptime m_last_scrape; - - // the time when we switched to upload mode - ptime m_upload_mode_time; - boost::intrusive_ptr m_torrent_file; - void parse_response(const entry& e, std::vector& peer_list); - // if this pointer is 0, the torrent is in // a state where the metadata hasn't been // received yet. @@ -859,40 +862,9 @@ namespace libtorrent extension_list_t m_extensions; #endif - // used to resolve the names of web seeds - mutable tcp::resolver m_host_resolver; - -#ifndef TORRENT_DISABLE_DHT - // this announce timer is used both - // by Local service discovery and - // by the DHT. - deadline_timer m_dht_announce_timer; -#endif - // used for tracker announces deadline_timer m_tracker_timer; - void update_tracker_timer(); - - static void on_tracker_announce_disp(boost::weak_ptr p - , error_code const& e); - - void on_tracker_announce(); - - void dht_announce(); - -#ifndef TORRENT_DISABLE_DHT - static void on_dht_announce_response_disp(boost::weak_ptr t - , std::vector const& peers); - void on_dht_announce_response(std::vector const& peers); - bool should_announce_dht() const; - void on_dht_announce(error_code const& e); - - // the time when the DHT was last announced of our - // presence on this torrent - ptime m_last_dht_announce; -#endif - // this is the upload and download statistics for the whole torrent. // it's updated from all its peers once every second. libtorrent::stat m_stat; @@ -933,32 +905,15 @@ namespace libtorrent { return deadline < rhs.deadline; } }; - void remove_time_critical_piece(int piece, bool finished = false); - void remove_time_critical_pieces(std::vector const& priority); - void request_time_critical_pieces(); - // this list is sorted by time_critical_piece::deadline std::list m_time_critical_pieces; - // the average time it takes to download one time critical piece - time_duration m_average_piece_time; - // the average piece download time deviation - time_duration m_piece_time_deviation; - - // the number of bytes that has been - // downloaded that failed the hash-test - size_type m_total_failed_bytes; - size_type m_total_redundant_bytes; - - // the number of bytes of padding files - int m_padding; - std::string m_username; std::string m_password; // the network interface all outgoing connections // are opened through - tcp::endpoint m_net_interface; + union_endpoint m_net_interface; std::string m_save_path; @@ -967,18 +922,6 @@ namespace libtorrent // is only used in seed mode (when m_seed_mode // is true) bitfield m_verified; - // m_num_verified = m_verified.count() - int m_num_verified; - - // free download we have got that hasn't - // been distributed yet. - size_type m_available_free_upload; - - // determines the storage state for this torrent. - storage_mode_t m_storage_mode; - - // the state of this torrent (queued, checking, downloading, etc.) - torrent_status::state_t m_state; // set if there's an error on this torrent error_code m_error; @@ -995,114 +938,75 @@ namespace libtorrent // longer be used and will be reset boost::scoped_ptr m_name; + storage_constructor_type m_storage_constructor; + #ifndef TORRENT_DISABLE_ENCRYPTION // this is SHA1("req2" + info-hash), used for // encrypted hand shakes sha1_hash m_obfuscated_hash; #endif - session_settings const& m_settings; - - storage_constructor_type m_storage_constructor; - - int m_progress_ppm; // the upload/download ratio that each peer // tries to maintain. // 0 is infinite float m_ratio; - // the maximum number of uploads for this torrent - int m_max_uploads; + // free download we have got that hasn't + // been distributed yet. + boost::uint32_t m_available_free_upload; - // the number of unchoked peers in this torrent - int m_num_uploads; + // the average time it takes to download one time critical piece + boost::uint32_t m_average_piece_time; + // the average piece download time deviation + boost::uint32_t m_piece_time_deviation; - // the maximum number of connections for this torrent - int m_max_connections; + // the number of bytes that has been + // downloaded that failed the hash-test + boost::uint32_t m_total_failed_bytes; + boost::uint32_t m_total_redundant_bytes; - // the size of a request block - // each piece is divided into these - // blocks when requested - int m_block_size; + // ============================== + // The following members are specifically + // ordered to make the 24 bit members + // properly 32 bit aligned by inserting + // 8 bits after each one + // ============================== - // ----------------------------- - // DATA FROM TRACKER RESPONSE + // the number of seconds we've been in upload mode + unsigned int m_upload_mode_time:24; - // the scrape data from the tracker response, this - // is optional and may be -1. - int m_complete; - int m_incomplete; + // the state of this torrent (queued, checking, downloading, etc.) + unsigned int m_state:3; -#ifdef TORRENT_DEBUG - // this is the amount downloaded when this torrent - // is started. i.e. - // total_done - m_initial_done <= total_payload_download - size_type m_initial_done; -#endif - // this is the deficit counter in the Deficit Round Robin - // used to determine which torrent gets the next - // connection attempt. See: - // http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf - // The quanta assigned to each torrent depends on the torrents - // priority, whether it's a seed and the number of connected - // peers it has. This has the effect that some torrents - // will have more connection attempts than other. Each - // connection attempt costs 100 points from the deficit - // counter. points are deducted in try_connect_peer and - // increased in give_connect_points. Outside of the - // torrent object, these points are called connect_points. - int m_deficit_counter; + // determines the storage state for this torrent. + unsigned int m_storage_mode:2; - // the sequence number for this torrent, this is a - // monotonically increasing number for each added torrent - boost::int16_t m_sequence_number; + // this is true while tracker announcing is enabled + // is is disabled while paused and checking files + bool m_announcing:1; + + // this is true while the tracker deadline timer + // is in use. i.e. one or more trackers are waiting + // for a reannounce + bool m_waiting_tracker:1; + + // this means we haven't verified the file content + // of the files we're seeding. the m_verified bitfield + // indicates which pieces have been verified and which + // haven't + bool m_seed_mode:1; + + // total time we've been available on this torrent + // does not count when the torrent is stopped or paused + // in seconds + unsigned int m_active_time:24; // the index to the last tracker that worked boost::int8_t m_last_working_tracker; - // the number of connection attempts that has - // failed in a row, this is currently used to - // determine the timeout until next try. - boost::int8_t m_failed_trackers; - - // this is a counter that is decreased every - // second, and when it reaches 0, the policy::pulse() - // is called and the time scaler is reset to 10. - boost::int8_t m_time_scaler; - - // this is the priority of the torrent. The higher - // the value is, the more bandwidth is assigned to - // the torrent's peers - boost::uint8_t m_priority; - - // is set to true when the torrent has - // been aborted. - bool m_abort:1; - - // is true if this torrent has been paused - bool m_paused:1; - - // set to true when this torrent may not download anything - bool m_upload_mode:1; - - // if this is true, libtorrent may pause and resume - // this torrent depending on queuing rules. Torrents - // started with auto_managed flag set may be added in - // a paused state in case there are no available - // slots. - bool m_auto_managed:1; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // this is true while there is a country - // resolution in progress. To avoid flodding - // the DNS request queue, only one ip is resolved - // at a time. - mutable bool m_resolving_country:1; - - // this is true if the user has enabled - // country resolution in this torrent - bool m_resolve_countries:1; -#endif + // total time we've been finished with this torrent + // does not count when the torrent is stopped or paused + unsigned int m_finished_time:24; // in case the piece picker hasn't been constructed // when this settings is set, this variable will keep @@ -1129,6 +1033,61 @@ namespace libtorrent // torrent. bool m_super_seeding:1; + // this is set when we don't want to load seed_mode, + // paused or auto_managed from the resume data + bool m_override_resume_data:1; + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + // this is true while there is a country + // resolution in progress. To avoid flodding + // the DNS request queue, only one ip is resolved + // at a time. + mutable bool m_resolving_country:1; + + // this is true if the user has enabled + // country resolution in this torrent + bool m_resolve_countries:1; +#else + unsigned int m_dummy_padding_bits_to_align:2; +#endif + // TODO: Add new bools here! + unsigned int m_dummy_padding_bit_to_alignt:1; + + // total time we've been available as a seed on this torrent + // does not count when the torrent is stopped or paused + unsigned int m_seeding_time:24; + + // this is a counter that is decreased every + // second, and when it reaches 0, the policy::pulse() + // is called and the time scaler is reset to 10. + boost::int8_t m_time_scaler; + + // the maximum number of uploads for this torrent + unsigned int m_max_uploads:24; + + // this is the deficit counter in the Deficit Round Robin + // used to determine which torrent gets the next + // connection attempt. See: + // http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf + // The quanta assigned to each torrent depends on the torrents + // priority, whether it's a seed and the number of connected + // peers it has. This has the effect that some torrents + // will have more connection attempts than other. Each + // connection attempt costs 100 points from the deficit + // counter. points are deducted in try_connect_peer and + // increased in give_connect_points. Outside of the + // torrent object, these points are called connect_points. + boost::uint8_t m_deficit_counter; + + // the number of unchoked peers in this torrent + unsigned int m_num_uploads:24; + + // the size of a request block + // each piece is divided into these + // blocks when requested. The block size is + // 1 << m_block_size_shift + unsigned int m_block_size_shift:5; + // is set to true every time there is an incoming // connection to this torrent bool m_has_incoming:1; @@ -1142,24 +1101,56 @@ namespace libtorrent // checking queue in the session bool m_queued_for_checking:1; - // this is true while tracker announcing is enabled - // is is disabled while paused and checking files - bool m_announcing:1; + // the maximum number of connections for this torrent + unsigned int m_max_connections:24; - // this is true while the tracker deadline timer - // is in use. i.e. one or more trackers are waiting - // for a reannounce - bool m_waiting_tracker:1; + // the number of bytes of padding files + unsigned int m_padding:24; - // this means we haven't verified the file content - // of the files we're seeding. the m_verified bitfield - // indicates which pieces have been verified and which - // haven't - bool m_seed_mode:1; + // the sequence number for this torrent, this is a + // monotonically increasing number for each added torrent + boost::int16_t m_sequence_number; - // this is set when we don't want to load seed_mode, - // paused or auto_managed from the resume data - bool m_override_resume_data:1; + // the scrape data from the tracker response, this + // is optional and may be 0xffffff + unsigned int m_complete:24; + + // this is the priority of the torrent. The higher + // the value is, the more bandwidth is assigned to + // the torrent's peers + boost::uint8_t m_priority; + + // the scrape data from the tracker response, this + // is optional and may be 0xffffff + unsigned int m_incomplete:24; + + // progress parts per million (the number of + // millionths of completeness) + unsigned int m_progress_ppm:20; + + // is set to true when the torrent has + // been aborted. + bool m_abort:1; + + // is true if this torrent has been paused + bool m_paused:1; + + // set to true when this torrent may not download anything + bool m_upload_mode:1; + + // if this is true, libtorrent may pause and resume + // this torrent depending on queuing rules. Torrents + // started with auto_managed flag set may be added in + // a paused state in case there are no available + // slots. + bool m_auto_managed:1; + + // m_num_verified = m_verified.count() + boost::uint16_t m_num_verified; + + // the number of seconds since the last scrape request to + // one of the trackers in this torrent + boost::uint16_t m_last_scrape; }; } diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 7cbcf85bf..f3985312a 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -62,6 +62,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/connection_queue.hpp" #include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/size_type.hpp" +#include "libtorrent/union_endpoint.hpp" namespace libtorrent { @@ -141,7 +142,7 @@ namespace libtorrent , const std::string& description , int retry_interval) = 0; - tcp::endpoint m_tracker_address; + union_endpoint m_tracker_address; #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING virtual void debug_log(const std::string& line) = 0; diff --git a/src/lazy_bdecode.cpp b/src/lazy_bdecode.cpp index 73531c0d9..e3b10ced1 100644 --- a/src/lazy_bdecode.cpp +++ b/src/lazy_bdecode.cpp @@ -203,7 +203,7 @@ namespace libtorrent lazy_dict_entry* tmp = new (std::nothrow) lazy_dict_entry[capacity]; if (tmp == 0) return 0; std::memcpy(tmp, m_data.dict, sizeof(lazy_dict_entry) * m_size); - for (int i = 0; i < m_size; ++i) m_data.dict[i].val.release(); + for (int i = 0; i < int(m_size); ++i) m_data.dict[i].val.release(); delete[] m_data.dict; m_data.dict = tmp; m_capacity = capacity; @@ -262,7 +262,7 @@ namespace libtorrent std::pair lazy_entry::dict_at(int i) const { TORRENT_ASSERT(m_type == dict_t); - TORRENT_ASSERT(i < m_size); + TORRENT_ASSERT(i < int(m_size)); lazy_dict_entry const& e = m_data.dict[i]; return std::make_pair(std::string(e.name, e.val.m_begin - e.name), &e.val); } @@ -319,7 +319,7 @@ namespace libtorrent lazy_entry* lazy_entry::dict_find(char const* name) { TORRENT_ASSERT(m_type == dict_t); - for (int i = 0; i < m_size; ++i) + for (int i = 0; i < int(m_size); ++i) { lazy_dict_entry& e = m_data.dict[i]; if (string_equal(name, e.name, e.val.m_begin - e.name)) @@ -345,7 +345,7 @@ namespace libtorrent lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity]; if (tmp == 0) return 0; std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size); - for (int i = 0; i < m_size; ++i) m_data.list[i].release(); + for (int i = 0; i < int(m_size); ++i) m_data.list[i].release(); delete[] m_data.list; m_data.list = tmp; m_capacity = capacity; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 6d4e2680c..8888bd076 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1335,7 +1335,7 @@ namespace libtorrent return; } - if (m_suggested_pieces.size() > m_ses.m_settings.max_suggest_pieces) + if (int(m_suggested_pieces.size()) > m_ses.m_settings.max_suggest_pieces) m_suggested_pieces.erase(m_suggested_pieces.begin()); m_suggested_pieces.push_back(index); @@ -3520,7 +3520,7 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); assert(t); - for (int i = 0; i < m_have_piece.size(); ++i) + for (int i = 0; i < int(m_have_piece.size()); ++i) { if (m_have_piece[i] || !t->have_piece(i)) continue; #ifdef TORRENT_VERBOSE_LOGGING @@ -4546,7 +4546,7 @@ namespace libtorrent (*m_logger) << "read " << bytes_transferred << " bytes\n"; #endif // correct the dl quota usage, if not all of the buffer was actually read - TORRENT_ASSERT(bytes_transferred <= m_quota[download_channel]); + TORRENT_ASSERT(int(bytes_transferred) <= m_quota[download_channel]); m_quota[download_channel] -= bytes_transferred; if (m_disconnecting) @@ -4576,7 +4576,7 @@ namespace libtorrent TORRENT_ASSERT(m_statistics.last_protocol_downloaded() - cur_protocol_dl >= 0); size_type stats_diff = m_statistics.last_payload_downloaded() - cur_payload_dl + m_statistics.last_protocol_downloaded() - cur_protocol_dl; - TORRENT_ASSERT(stats_diff == bytes_transferred); + TORRENT_ASSERT(stats_diff == int(bytes_transferred)); #endif TORRENT_ASSERT(m_packet_size > 0); @@ -4860,7 +4860,7 @@ namespace libtorrent m_channel_state[upload_channel] = peer_info::bw_idle; - TORRENT_ASSERT(bytes_transferred <= m_quota[upload_channel]); + TORRENT_ASSERT(int(bytes_transferred) <= m_quota[upload_channel]); m_quota[upload_channel] -= bytes_transferred; m_statistics.trancieve_ip_packet(bytes_transferred, m_remote.address().is_v6()); @@ -4894,7 +4894,7 @@ namespace libtorrent TORRENT_ASSERT(m_statistics.last_protocol_uploaded() - cur_protocol_ul >= 0); size_type stats_diff = m_statistics.last_payload_uploaded() - cur_payload_ul + m_statistics.last_protocol_uploaded() - cur_protocol_ul; - TORRENT_ASSERT(stats_diff == bytes_transferred); + TORRENT_ASSERT(stats_diff == int(bytes_transferred)); #endif fill_send_buffer(); diff --git a/src/policy.cpp b/src/policy.cpp index c05981bb8..2804ee7ca 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -289,8 +289,8 @@ namespace libtorrent } policy::policy(torrent* t) - : m_round_robin(0) - , m_torrent(t) + : m_torrent(t) + , m_round_robin(0) , m_num_connect_candidates(0) , m_num_seeds(0) , m_finished(false) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 27558bcba..01e7a0b80 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -453,9 +453,12 @@ namespace aux { , m_external_udp_port(0) , m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4) , m_half_open) + , m_dht_announce_timer(m_io_service) #endif , m_timer(m_io_service) , m_lsd_announce_timer(m_io_service) + , m_host_resolver(m_io_service) + , m_tick_residual(0) #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , m_logpath(logpath) #endif @@ -466,6 +469,9 @@ namespace aux { , m_total_failed_bytes(0) , m_total_redundant_bytes(0) { +#ifndef TORRENT_DISABLE_DHT + m_next_dht_torrent = m_torrents.begin(); +#endif m_next_lsd_torrent = m_torrents.begin(); m_next_connect_torrent = m_torrents.begin(); @@ -507,6 +513,7 @@ namespace aux { #define PRINT_SIZEOF(x) (*m_logger) << "sizeof(" #x "): " << sizeof(x) << "\n"; #define PRINT_OFFSETOF(x, y) (*m_logger) << " offsetof(" #x "," #y "): " << offsetof(x, y) << "\n"; + PRINT_SIZEOF(union_endpoint) PRINT_SIZEOF(request_callback) PRINT_SIZEOF(stat) PRINT_SIZEOF(bandwidth_channel) @@ -621,6 +628,14 @@ namespace aux { m_lsd_announce_timer.async_wait( bind(&session_impl::on_lsd_announce, this, _1)); +#ifndef TORRENT_DISABLE_DHT + delay = (std::max)(m_settings.dht_announce_interval + / (std::max)(int(m_torrents.size()), 1), 1); + m_dht_announce_timer.expires_from_now(seconds(delay), ec); + m_dht_announce_timer.async_wait( + bind(&session_impl::on_dht_announce, this, _1)); +#endif + m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this))); } @@ -929,6 +944,7 @@ namespace aux { #ifndef TORRENT_DISABLE_DHT if (m_dht) m_dht->stop(); m_dht_socket.close(); + m_dht_announce_timer.cancel(ec); #endif m_timer.cancel(ec); m_lsd_announce_timer.cancel(ec); @@ -1086,6 +1102,18 @@ namespace aux { m_unchoke_time_scaler = 0; } +#ifndef TORRENT_DISABLE_DHT + if (m_settings.dht_announce_interval != s.dht_announce_interval) + { + error_code ec; + int delay = (std::max)(s.dht_announce_interval + / (std::max)(int(m_torrents.size()), 1), 1); + m_dht_announce_timer.expires_from_now(seconds(delay), ec); + m_dht_announce_timer.async_wait( + bind(&session_impl::on_dht_announce, this, _1)); + } +#endif + if (m_settings.local_service_announce_interval != s.local_service_announce_interval) { error_code ec; @@ -1745,6 +1773,7 @@ namespace aux { int tick_interval_ms = total_milliseconds(now - m_last_second_tick); m_last_second_tick = now; + m_tick_residual += tick_interval_ms - 1000; int session_time = total_seconds(now - m_created); if (session_time > 65000) @@ -1884,7 +1913,8 @@ namespace aux { { ++num_paused_auto_managed; if (least_recently_scraped == m_torrents.end() - || least_recently_scraped->second->last_scrape() > t.last_scrape()) + || least_recently_scraped->second->seconds_since_last_scrape() + < t.seconds_since_last_scrape()) { least_recently_scraped = i; } @@ -2191,9 +2221,36 @@ namespace aux { } } + while (m_tick_residual >= 1000) m_tick_residual -= 1000; // m_peer_pool.release_memory(); } +#ifndef TORRENT_DISABLE_DHT + + void session_impl::on_dht_announce(error_code const& e) + { + if (e) return; + + mutex::scoped_lock l(m_mutex); + if (m_abort) return; + + // announce to DHT every 15 minutes + int delay = (std::max)(m_settings.dht_announce_interval + / (std::max)(int(m_torrents.size()), 1), 1); + error_code ec; + m_dht_announce_timer.expires_from_now(seconds(delay), ec); + m_dht_announce_timer.async_wait( + bind(&session_impl::on_dht_announce, this, _1)); + + if (m_next_dht_torrent == m_torrents.end()) + m_next_dht_torrent = m_torrents.begin(); + m_next_dht_torrent->second->dht_announce(); + ++m_next_dht_torrent; + if (m_next_dht_torrent == m_torrents.end()) + m_next_dht_torrent = m_torrents.begin(); + } +#endif + void session_impl::on_lsd_announce(error_code const& e) { if (e) return; @@ -2895,6 +2952,10 @@ namespace aux { #ifdef TORRENT_DEBUG sha1_hash i_hash = t.torrent_file().info_hash(); +#endif +#ifndef TORRENT_DISABLE_DHT + if (i == m_next_dht_torrent) + ++m_next_dht_torrent; #endif if (i == m_next_lsd_torrent) ++m_next_lsd_torrent; @@ -2904,6 +2965,10 @@ namespace aux { t.set_queue_position(-1); m_torrents.erase(i); +#ifndef TORRENT_DISABLE_DHT + if (m_next_dht_torrent == m_torrents.end()) + m_next_dht_torrent = m_torrents.begin(); +#endif if (m_next_lsd_torrent == m_torrents.end()) m_next_lsd_torrent = m_torrents.begin(); if (m_next_connect_torrent == m_torrents.end()) @@ -3195,7 +3260,7 @@ namespace aux { for (torrent_map::const_iterator i = m_torrents.begin() , end(m_torrents.end()); i != end; ++i) { - i->second->force_dht_announce(); + i->second->dht_announce(); } } diff --git a/src/torrent.cpp b/src/torrent.cpp index 4b978db89..6b22d064e 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -199,36 +199,24 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING #define PRINT_SIZEOF(x) l << "sizeof(" #x "): " << sizeof(x) << "\n"; -#define PRINT_OFFSETOF(x, y) l << " offsetof(" #x "," #y "): " << offsetof(x, y) << "\n"; +#define PRINT_OFFSETOF(x, y) l << " " << (offsetof(x, y) - temp) << " offsetof(" #x "," #y "): " << offsetof(x, y) << "\n"; temp = offsetof(x, y); void torrent::print_size(logger& l) { + int temp = 0; PRINT_SIZEOF(torrent) + PRINT_OFFSETOF(torrent, m_policy) - PRINT_OFFSETOF(torrent, m_active_time) - PRINT_OFFSETOF(torrent, m_finished_time) - PRINT_OFFSETOF(torrent, m_seeding_time) PRINT_OFFSETOF(torrent, m_total_uploaded) PRINT_OFFSETOF(torrent, m_total_downloaded) PRINT_OFFSETOF(torrent, m_started) - PRINT_OFFSETOF(torrent, m_last_scrape) - PRINT_OFFSETOF(torrent, m_upload_mode_time) PRINT_OFFSETOF(torrent, m_torrent_file) PRINT_OFFSETOF(torrent, m_owning_storage) PRINT_OFFSETOF(torrent, m_storage) PRINT_OFFSETOF(torrent, m_connections) PRINT_OFFSETOF(torrent, m_web_seeds) -#ifndef TORRENT_DISABLE_EXTENSIONS PRINT_OFFSETOF(torrent, m_extensions) -#endif - PRINT_OFFSETOF(torrent, m_host_resolver) -#ifndef TORRENT_DISABLE_DHT - PRINT_OFFSETOF(torrent, m_dht_announce_timer) -#endif PRINT_OFFSETOF(torrent, m_tracker_timer) -#ifndef TORRENT_DISABLE_DHT - PRINT_OFFSETOF(torrent, m_last_dht_announce) -#endif PRINT_OFFSETOF(torrent, m_stat) PRINT_OFFSETOF(torrent, m_ses) PRINT_OFFSETOF(torrent, m_file_priority) @@ -236,53 +224,84 @@ namespace libtorrent PRINT_OFFSETOF(torrent, m_picker) PRINT_OFFSETOF(torrent, m_trackers) PRINT_OFFSETOF(torrent, m_time_critical_pieces) - PRINT_OFFSETOF(torrent, m_average_piece_time) - PRINT_OFFSETOF(torrent, m_piece_time_deviation) - PRINT_OFFSETOF(torrent, m_total_failed_bytes) - PRINT_OFFSETOF(torrent, m_total_redundant_bytes) - PRINT_OFFSETOF(torrent, m_padding) PRINT_OFFSETOF(torrent, m_username) PRINT_OFFSETOF(torrent, m_password) PRINT_OFFSETOF(torrent, m_net_interface) PRINT_OFFSETOF(torrent, m_save_path) PRINT_OFFSETOF(torrent, m_verified) - PRINT_OFFSETOF(torrent, m_num_verified) - PRINT_OFFSETOF(torrent, m_available_free_upload) - PRINT_OFFSETOF(torrent, m_storage_mode) - PRINT_OFFSETOF(torrent, m_state) PRINT_OFFSETOF(torrent, m_error) PRINT_OFFSETOF(torrent, m_error_file) PRINT_OFFSETOF(torrent, m_resume_data) PRINT_OFFSETOF(torrent, m_resume_entry) PRINT_OFFSETOF(torrent, m_name) -#ifndef TORRENT_DISABLE_ENCRYPTION - PRINT_OFFSETOF(torrent, m_obfuscated_hash) -#endif - PRINT_OFFSETOF(torrent, m_settings) PRINT_OFFSETOF(torrent, m_storage_constructor) - PRINT_OFFSETOF(torrent, m_progress_ppm) + PRINT_OFFSETOF(torrent, m_obfuscated_hash) PRINT_OFFSETOF(torrent, m_ratio) - PRINT_OFFSETOF(torrent, m_max_uploads) - PRINT_OFFSETOF(torrent, m_num_uploads) - PRINT_OFFSETOF(torrent, m_max_connections) - PRINT_OFFSETOF(torrent, m_block_size) - PRINT_OFFSETOF(torrent, m_complete) - PRINT_OFFSETOF(torrent, m_incomplete) -#ifdef TORRENT_DEBUG - PRINT_OFFSETOF(torrent, m_initial_done) -#endif - PRINT_OFFSETOF(torrent, m_deficit_counter) - PRINT_OFFSETOF(torrent, m_sequence_number) + PRINT_OFFSETOF(torrent, m_available_free_upload) + PRINT_OFFSETOF(torrent, m_average_piece_time) + PRINT_OFFSETOF(torrent, m_piece_time_deviation) + PRINT_OFFSETOF(torrent, m_total_failed_bytes) + PRINT_OFFSETOF(torrent, m_total_redundant_bytes) +// PRINT_OFFSETOF(torrent, m_upload_mode_time:24) +// PRINT_OFFSETOF(torrent, m_state:3) +// PRINT_OFFSETOF(torrent, m_storage_mode:2) +// PRINT_OFFSETOF(torrent, m_announcing:1) +// PRINT_OFFSETOF(torrent, m_waiting_tracker:1) +// PRINT_OFFSETOF(torrent, m_seed_mode:1) +// PRINT_OFFSETOF(torrent, m_active_time:24) PRINT_OFFSETOF(torrent, m_last_working_tracker) - PRINT_OFFSETOF(torrent, m_failed_trackers) +// PRINT_OFFSETOF(torrent, m_finished_time:24) +// PRINT_OFFSETOF(torrent, m_sequential_download:1) +// PRINT_OFFSETOF(torrent, m_got_tracker_response:1) +// PRINT_OFFSETOF(torrent, m_connections_initialized:1) +// PRINT_OFFSETOF(torrent, m_super_seeding:1) +// PRINT_OFFSETOF(torrent, m_override_resume_data:1) +// PRINT_OFFSETOF(torrent, m_resolving_country:1) +// PRINT_OFFSETOF(torrent, m_resolve_countries:1) +// PRINT_OFFSETOF(torrent, m_dummy_padding_bit_to_align:1) +// PRINT_OFFSETOF(torrent, m_seeding_time:24) PRINT_OFFSETOF(torrent, m_time_scaler) +// PRINT_OFFSETOF(torrent, m_max_uploads:24) + PRINT_OFFSETOF(torrent, m_deficit_counter) +// PRINT_OFFSETOF(torrent, m_num_uploads:24) +// PRINT_OFFSETOF(torrent, m_block_size_shift:5) +// PRINT_OFFSETOF(torrent, m_has_incoming:1) +// PRINT_OFFSETOF(torrent, m_files_checked:1) +// PRINT_OFFSETOF(torrent, m_queued_for_checking:1) +// PRINT_OFFSETOF(torrent, m_max_connections:24) +// PRINT_OFFSETOF(torrent, m_padding:24) + PRINT_OFFSETOF(torrent, m_sequence_number) +// PRINT_OFFSETOF(torrent, m_complete:24) PRINT_OFFSETOF(torrent, m_priority) +// PRINT_OFFSETOF(torrent, m_incomplete:24) +// PRINT_OFFSETOF(torrent, m_progress_ppm:20) +// PRINT_OFFSETOF(torrent, m_abort:1) +// PRINT_OFFSETOF(torrent, m_paused:1) +// PRINT_OFFSETOF(torrent, m_upload_mode:1) +// PRINT_OFFSETOF(torrent, m_auto_managed:1) + PRINT_OFFSETOF(torrent, m_num_verified) + PRINT_OFFSETOF(torrent, m_last_scrape) } #undef PRINT_SIZEOF #undef PRINT_OFFSETOF #endif + int root2(int x) + { + int ret = 0; + x >>= 1; + while (x > 0) + { + // if this assert triggers, the block size + // is not an even 2 exponent! + TORRENT_ASSERT(x == 1 || (x & 1) == 0); + ++ret; + x >>= 1; + } + return ret; + } + torrent::torrent( session_impl& ses , tcp::endpoint const& net_interface @@ -290,79 +309,70 @@ namespace libtorrent , int seq , add_torrent_params const& p) : m_policy(this) - , m_active_time(seconds(0)) - , m_finished_time(seconds(0)) - , m_seeding_time(seconds(0)) , m_total_uploaded(0) , m_total_downloaded(0) , m_started(time_now()) - , m_last_scrape(min_time()) - , m_upload_mode_time(time_now()) , m_torrent_file(p.ti ? p.ti : new torrent_info(p.info_hash)) , m_storage(0) - , m_host_resolver(ses.m_io_service) -#ifndef TORRENT_DISABLE_DHT - , m_dht_announce_timer(ses.m_io_service) -#endif , m_tracker_timer(ses.m_io_service) -#ifndef TORRENT_DISABLE_DHT - , m_last_dht_announce(time_now() - minutes(15)) -#endif , m_ses(ses) , m_trackers(m_torrent_file->trackers()) - , m_average_piece_time(seconds(0)) - , m_piece_time_deviation(seconds(0)) + , m_net_interface(tcp::endpoint(net_interface.address(), 0)) + , m_save_path(complete(p.save_path)) + , m_storage_constructor(p.storage) + , m_ratio(0.f) + , m_available_free_upload(0) + , m_average_piece_time(0) + , m_piece_time_deviation(0) , m_total_failed_bytes(0) , m_total_redundant_bytes(0) - , m_padding(0) - , m_net_interface(net_interface.address(), 0) - , m_save_path(complete(p.save_path)) - , m_num_verified(0) - , m_available_free_upload(0) - , m_storage_mode(p.storage_mode) + , m_upload_mode_time(0) , m_state(torrent_status::checking_resume_data) - , m_settings(ses.settings()) - , m_storage_constructor(p.storage) - , m_progress_ppm(0) - , m_ratio(0.f) - , m_max_uploads((std::numeric_limits::max)()) - , m_num_uploads(0) - , m_max_connections((std::numeric_limits::max)()) - , m_block_size(p.ti ? (std::min)(block_size, m_torrent_file->piece_length()) : block_size) - , m_complete(-1) - , m_incomplete(-1) - , m_deficit_counter(0) - , m_sequence_number(seq) + , m_storage_mode(p.storage_mode) + , m_announcing(false) + , m_waiting_tracker(false) + , m_seed_mode(p.seed_mode && m_torrent_file->is_valid()) + , m_active_time(0) , m_last_working_tracker(-1) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_priority(0) - , m_abort(false) - , m_paused(p.paused) - , m_upload_mode(p.upload_mode) - , m_auto_managed(p.auto_managed) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif + , m_finished_time(0) , m_sequential_download(false) , m_got_tracker_response(false) , m_connections_initialized(p.ti) , m_super_seeding(false) + , m_override_resume_data(p.override_resume_data) +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + , m_resolving_country(false) + , m_resolve_countries(false) +#endif + , m_seeding_time(0) + , m_time_scaler(0) + , m_max_uploads(~0) + , m_deficit_counter(0) + , m_num_uploads(0) + , m_block_size_shift(root2(p.ti ? (std::min)(block_size, m_torrent_file->piece_length()) : block_size)) , m_has_incoming(false) , m_files_checked(false) , m_queued_for_checking(false) - , m_announcing(false) - , m_waiting_tracker(false) - , m_seed_mode(p.seed_mode && m_torrent_file->is_valid()) - , m_override_resume_data(p.override_resume_data) + , m_max_connections(~0) + , m_padding(0) + , m_sequence_number(seq) + , m_complete(~1) + , m_priority(0) + , m_incomplete(~1) + , m_progress_ppm(0) + , m_abort(false) + , m_paused(p.paused) + , m_upload_mode(p.upload_mode) + , m_auto_managed(p.auto_managed) + , m_num_verified(0) + , m_last_scrape(0) { if (m_seed_mode) m_verified.resize(m_torrent_file->num_pieces(), false); if (p.resume_data) m_resume_data.swap(*p.resume_data); - if (m_settings.prefer_udp_trackers) + if (settings().prefer_udp_trackers) prioritize_udp_trackers(); #ifndef TORRENT_DISABLE_ENCRYPTION @@ -441,7 +451,7 @@ namespace libtorrent // don't announce private torrents if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; if (m_trackers.empty()) return true; - if (!m_settings.use_dht_as_fallback) return true; + if (!settings().use_dht_as_fallback) return true; int verified_trackers = 0; for (std::vector::const_iterator i = m_trackers.begin() @@ -451,16 +461,6 @@ namespace libtorrent return verified_trackers == 0; } - void torrent::force_dht_announce() - { - m_last_dht_announce = min_time(); - // DHT announces are done on the local service - // discovery timer. Trigger it. - error_code ec; - m_dht_announce_timer.expires_from_now(seconds(1), ec); - m_dht_announce_timer.async_wait( - bind(&torrent::on_dht_announce, shared_from_this(), _1)); - } #endif torrent::~torrent() @@ -495,7 +495,7 @@ namespace libtorrent { TORRENT_ASSERT(piece >= 0 && piece < m_torrent_file->num_pieces()); int piece_size = m_torrent_file->piece_size(piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int blocks_in_piece = (piece_size + block_size() - 1) / block_size(); read_piece_struct* rp = new read_piece_struct; rp->piece_data.reset(new (std::nothrow) char[piece_size]); @@ -505,9 +505,9 @@ namespace libtorrent peer_request r; r.piece = piece; r.start = 0; - for (int i = 0; i < blocks_in_piece; ++i, r.start += m_block_size) + for (int i = 0; i < blocks_in_piece; ++i, r.start += block_size()) { - r.length = (std::min)(piece_size - r.start, m_block_size); + r.length = (std::min)(piece_size - r.start, block_size()); filesystem().async_read(r, bind(&torrent::on_disk_read_complete , shared_from_this(), _1, _2, r, rp)); ++rp->blocks_left; @@ -545,7 +545,7 @@ namespace libtorrent p->cancel_all_requests(); } // this is used to try leaving upload only mode periodically - m_upload_mode_time = time_now(); + m_upload_mode_time = 0; } else { @@ -657,7 +657,7 @@ namespace libtorrent { TORRENT_ASSERT(piece >= 0 && piece < m_torrent_file->num_pieces()); int piece_size = m_torrent_file->piece_size(piece); - int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; + int blocks_in_piece = (piece_size + block_size() - 1) / block_size(); // avoid crash trying to access the picker when there is nont if (is_seed()) return; @@ -666,13 +666,13 @@ namespace libtorrent p.piece = piece; p.start = 0; picker().inc_refcount(piece); - for (int i = 0; i < blocks_in_piece; ++i, p.start += m_block_size) + for (int i = 0; i < blocks_in_piece; ++i, p.start += block_size()) { if (picker().is_finished(piece_block(piece, i)) && (flags & torrent::overwrite_existing) == 0) continue; - p.length = (std::min)(piece_size - p.start, m_block_size); + p.length = (std::min)(piece_size - p.start, int(block_size())); char* buffer = m_ses.allocate_disk_buffer("add piece"); // out of memory if (buffer == 0) @@ -704,11 +704,11 @@ namespace libtorrent if (m_abort) { - piece_block block_finished(p.piece, p.start / m_block_size); + piece_block block_finished(p.piece, p.start / block_size()); return; } - piece_block block_finished(p.piece, p.start / m_block_size); + piece_block block_finished(p.piece, p.start / block_size()); if (ret == -1) { @@ -746,16 +746,16 @@ namespace libtorrent peer_request torrent::to_req(piece_block const& p) { - int block_offset = p.block_index * m_block_size; - int block_size = (std::min)(torrent_file().piece_size( - p.piece_index) - block_offset, m_block_size); - TORRENT_ASSERT(block_size > 0); - TORRENT_ASSERT(block_size <= m_block_size); + int block_offset = p.block_index * block_size(); + int block = (std::min)(torrent_file().piece_size( + p.piece_index) - block_offset, int(block_size())); + TORRENT_ASSERT(block > 0); + TORRENT_ASSERT(block <= block_size()); peer_request r; r.piece = p.piece_index; r.start = block_offset; - r.length = block_size; + r.length = block; return r; } @@ -808,7 +808,7 @@ namespace libtorrent m_file_priority.resize(m_torrent_file->num_files(), 1); m_file_progress.resize(m_torrent_file->num_files(), 0); - m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length()); + m_block_size_shift = root2((std::min)(int(block_size()), m_torrent_file->piece_length())); if (m_torrent_file->num_pieces() > piece_picker::max_pieces) { @@ -820,13 +820,13 @@ namespace libtorrent // 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_mode); + , (storage_mode_t)m_storage_mode); m_storage = m_owning_storage.get(); if (has_picker()) { - m_picker->init((std::max)(m_torrent_file->piece_length() / m_block_size, 1) - , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); + m_picker->init((std::max)(m_torrent_file->piece_length() / block_size(), 1) + , int((m_torrent_file->total_size()+block_size()-1) / block_size())); } std::vector const& url_seeds = m_torrent_file->url_seeds(); @@ -884,7 +884,7 @@ namespace libtorrent } } - TORRENT_ASSERT(m_block_size > 0); + TORRENT_ASSERT(block_size() > 0); int file = 0; for (file_storage::iterator i = m_torrent_file->files().begin() , end(m_torrent_file->files().end()); i != end; ++i, ++file) @@ -893,13 +893,14 @@ namespace libtorrent m_padding += i->size; peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size); - int off = pr.start & (m_block_size-1); - if (off != 0) { pr.length -= m_block_size - off; pr.start += m_block_size - off; } - TORRENT_ASSERT((pr.start & (m_block_size-1)) == 0); + int off = pr.start & (block_size()-1); + if (off != 0) { pr.length -= block_size() - off; pr.start += block_size() - off; } + TORRENT_ASSERT((pr.start & (block_size()-1)) == 0); - int blocks_per_piece = m_torrent_file->piece_length() / m_block_size; - piece_block pb(pr.piece, pr.start / m_block_size); - for (; pr.length >= m_block_size; pr.length -= m_block_size, ++pb.block_index) + int block = block_size(); + int blocks_per_piece = m_torrent_file->piece_length() / block; + piece_block pb(pr.piece, pr.start / block_size()); + for (; pr.length >= block; pr.length -= block, ++pb.block_index) { if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; } m_picker->mark_as_finished(pb, 0); @@ -1142,8 +1143,8 @@ namespace libtorrent m_owning_storage->async_release_files(); if (!m_picker) m_picker.reset(new piece_picker()); std::fill(m_file_progress.begin(), m_file_progress.end(), 0); - m_picker->init(m_torrent_file->piece_length() / m_block_size - , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)); + m_picker->init(m_torrent_file->piece_length() / block_size() + , int((m_torrent_file->total_size() + block_size()-1)/block_size())); // assume that we don't have anything TORRENT_ASSERT(m_picker->num_have() == 0); m_files_checked = false; @@ -1277,7 +1278,7 @@ namespace libtorrent if (m_torrent_file->is_valid() && (m_torrent_file->priv() || (torrent_file().is_i2p() - && !m_settings.allow_i2p_mixed))) + && !settings().allow_i2p_mixed))) return; if (is_paused()) return; @@ -1288,18 +1289,8 @@ namespace libtorrent #ifndef TORRENT_DISABLE_DHT - void torrent::on_dht_announce(error_code const& e) + void torrent::dht_announce() { - if (e) return; - - mutex::scoped_lock l(m_ses.m_mutex); - if (m_abort) return; - - error_code ec; - m_dht_announce_timer.expires_from_now(minutes(15), ec); - m_dht_announce_timer.async_wait( - bind(&torrent::on_dht_announce, shared_from_this(), _1)); - if (m_torrent_file->is_valid() && m_torrent_file->priv()) return; @@ -1307,12 +1298,12 @@ namespace libtorrent if (!m_ses.m_dht) return; if (!should_announce_dht()) return; - m_last_dht_announce = time_now(); boost::weak_ptr self(shared_from_this()); m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.listen_port() , bind(&torrent::on_dht_announce_response_disp, self, _1)); - } + } + void torrent::on_dht_announce_response_disp(boost::weak_ptr t , std::vector const& peers) { @@ -1332,7 +1323,7 @@ namespace libtorrent } if (torrent_file().priv() || (torrent_file().is_i2p() - && !m_settings.allow_i2p_mixed)) return; + && !settings().allow_i2p_mixed)) return; std::for_each(peers.begin(), peers.end(), bind( &policy::add_peer, boost::ref(m_policy), _1, peer_id(0) @@ -1367,7 +1358,7 @@ namespace libtorrent // if we are aborting. we don't want any new peers req.num_want = (req.event == tracker_request::stopped) - ?0:m_settings.num_want; + ?0:settings().num_want; req.listen_port = m_ses.listen_port(); req.key = m_ses.m_key; @@ -1385,13 +1376,13 @@ namespace libtorrent for (int i = 0; i < int(m_trackers.size()); ++i) { announce_entry& ae = m_trackers[i]; - if (m_settings.announce_to_all_tiers + if (settings().announce_to_all_tiers && sent_announce && ae.tier <= tier && tier != INT_MAX) continue; - if (ae.tier > tier && !m_settings.announce_to_all_tiers) break; + if (ae.tier > tier && !settings().announce_to_all_tiers) break; if (ae.is_working()) { tier = ae.tier; sent_announce = false; } if (!ae.can_announce(now)) { @@ -1399,8 +1390,8 @@ namespace libtorrent { sent_announce = true; // this counts - if (!m_settings.announce_to_all_trackers - && !m_settings.announce_to_all_tiers) + if (!settings().announce_to_all_trackers + && !settings().announce_to_all_tiers) break; } continue; @@ -1442,8 +1433,8 @@ namespace libtorrent sent_announce = true; if (ae.is_working() - && !m_settings.announce_to_all_trackers - && !m_settings.announce_to_all_tiers) + && !settings().announce_to_all_trackers + && !settings().announce_to_all_tiers) break; } update_tracker_timer(); @@ -1451,7 +1442,7 @@ namespace libtorrent void torrent::scrape_tracker() { - m_last_scrape = time_now(); + m_last_scrape = 0; if (m_trackers.empty()) return; @@ -1516,8 +1507,8 @@ namespace libtorrent ptime now = time_now(); - if (interval < m_settings.min_announce_interval) - interval = m_settings.min_announce_interval; + if (interval < settings().min_announce_interval) + interval = settings().min_announce_interval; announce_entry* ae = find_tracker(r); if (ae) @@ -1539,7 +1530,7 @@ namespace libtorrent if (complete >= 0) m_complete = complete; if (incomplete >= 0) m_incomplete = incomplete; if (complete >= 0 && incomplete >= 0) - m_last_scrape = now; + m_last_scrape = 0; #if (defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING) && TORRENT_USE_IOSTREAM std::stringstream s; @@ -1598,7 +1589,7 @@ namespace libtorrent #endif { tcp::resolver::query q(i->ip, to_string(i->port).elems); - m_host_resolver.async_resolve(q, + m_ses.m_host_resolver.async_resolve(q, bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid)); } } @@ -1768,19 +1759,19 @@ namespace libtorrent } // returns the number of bytes we are interested - // in for the given block. This returns m_block_size + // in for the given block. This returns block_size() // for all blocks except the last one (if it's smaller - // than m_block_size) and blocks that overlap a padding + // than block_size()) and blocks that overlap a padding // file int torrent::block_bytes_wanted(piece_block const& p) const { file_storage const& fs = m_torrent_file->files(); int piece_size = m_torrent_file->piece_size(p.piece_index); - int offset = p.block_index * m_block_size; - if (m_padding == 0) return (std::min)(piece_size - offset, m_block_size); + int offset = p.block_index * block_size(); + if (m_padding == 0) return (std::min)(piece_size - offset, int(block_size())); std::vector files = fs.map_block( - p.piece_index, offset, (std::min)(piece_size - offset, m_block_size)); + p.piece_index, offset, (std::min)(piece_size - offset, int(block_size()))); int ret = 0; for (std::vector::iterator i = files.begin() , end(files.end()); i != end; ++i) @@ -1789,7 +1780,7 @@ namespace libtorrent if (fe.pad_file) continue; ret += i->size; } - TORRENT_ASSERT(ret <= (std::min)(piece_size - offset, m_block_size)); + TORRENT_ASSERT(ret <= (std::min)(piece_size - offset, int(block_size()))); return ret; } @@ -1889,7 +1880,7 @@ namespace libtorrent const std::vector& dl_queue = m_picker->get_download_queue(); - const int blocks_per_piece = (piece_size + m_block_size - 1) / m_block_size; + const int blocks_per_piece = (piece_size + block_size() - 1) / block_size(); // look at all unfinished pieces and add the completed // blocks to our 'done' counter @@ -2405,7 +2396,7 @@ namespace libtorrent set_state(torrent_status::queued_for_checking); m_owning_storage = 0; - m_host_resolver.cancel(); + m_ses.m_host_resolver.cancel(); } void torrent::super_seeding(bool on) @@ -2611,18 +2602,16 @@ namespace libtorrent // update the average download time and average // download time deviation - time_duration dl_time = time_now() - i->first_requested; + int dl_time = total_milliseconds(time_now() - i->first_requested); - if (m_average_piece_time == seconds(0)) + if (m_average_piece_time == 0) { m_average_piece_time = dl_time; } else { - time_duration diff = dl_time > m_average_piece_time - ? dl_time - m_average_piece_time - : m_average_piece_time - dl_time; - if (m_piece_time_deviation == seconds(0)) m_piece_time_deviation = diff; + int diff = abs(dl_time - m_average_piece_time); + if (m_piece_time_deviation == 0) m_piece_time_deviation = diff; else m_piece_time_deviation = (m_piece_time_deviation * 6 + diff * 4) / 10; m_average_piece_time = (m_average_piece_time * 6 + dl_time * 4) / 10; @@ -2982,7 +2971,7 @@ namespace libtorrent , end(m_trackers.end()); i != end; ++i) if (i->source == 0) i->source = announce_entry::source_client; - if (m_settings.prefer_udp_trackers) + if (settings().prefer_udp_trackers) prioritize_udp_trackers(); if (!m_trackers.empty()) start_announcing(); @@ -3224,7 +3213,7 @@ namespace libtorrent { // use proxy tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); - m_host_resolver.async_resolve(q, + m_ses.m_host_resolver.async_resolve(q, bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, web)); } else @@ -3242,7 +3231,7 @@ namespace libtorrent } tcp::resolver::query q(hostname, to_string(port).elems); - m_host_resolver.async_resolve(q, + m_ses.m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, web , tcp::endpoint())); } @@ -3307,7 +3296,7 @@ namespace libtorrent } tcp::resolver::query q(hostname, to_string(port).elems); - m_host_resolver.async_resolve(q, + m_ses.m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, web, a)); } @@ -3450,7 +3439,7 @@ namespace libtorrent return; } m_resolving_country = true; - m_host_resolver.async_resolve(q, + m_ses.m_host_resolver.async_resolve(q, bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)); } @@ -3568,9 +3557,9 @@ namespace libtorrent { m_total_uploaded = rd.dict_find_int_value("total_uploaded"); m_total_downloaded = rd.dict_find_int_value("total_downloaded"); - m_active_time = seconds(rd.dict_find_int_value("active_time")); - m_finished_time = seconds(rd.dict_find_int_value("finished_time")); - m_seeding_time = seconds(rd.dict_find_int_value("seeding_time")); + m_active_time = rd.dict_find_int_value("active_time"); + m_finished_time = rd.dict_find_int_value("finished_time"); + m_seeding_time = rd.dict_find_int_value("seeding_time"); m_complete = rd.dict_find_int_value("num_seeds", -1); m_incomplete = rd.dict_find_int_value("num_downloaders", -1); set_upload_limit(rd.dict_find_int_value("upload_rate_limit", -1)); @@ -3637,7 +3626,7 @@ namespace libtorrent std::sort(m_trackers.begin(), m_trackers.end(), boost::bind(&announce_entry::tier, _1) < boost::bind(&announce_entry::tier, _2)); - if (m_settings.prefer_udp_trackers) + if (settings().prefer_udp_trackers) prioritize_udp_trackers(); } @@ -3710,9 +3699,9 @@ namespace libtorrent ret["total_uploaded"] = m_total_uploaded; ret["total_downloaded"] = m_total_downloaded; - ret["active_time"] = total_seconds(m_active_time); - ret["finished_time"] = total_seconds(m_finished_time); - ret["seeding_time"] = total_seconds(m_seeding_time); + ret["active_time"] = m_active_time; + ret["finished_time"] = m_finished_time; + ret["seeding_time"] = m_seeding_time; int seeds = 0; int downloaders = 0; @@ -3875,7 +3864,7 @@ namespace libtorrent #endif // failcount is a 5 bit value - int max_failcount = (std::min)(m_ses.m_settings.max_failcount, 31); + int max_failcount = (std::min)(settings().max_failcount, 31); for (policy::const_iterator i = m_policy.begin_peer() , end(m_policy.end_peer()); i != end; ++i) @@ -4011,8 +4000,8 @@ namespace libtorrent { block_info& bi = pi.blocks[j]; bi.state = i->info[j].state; - bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size - : piece_size - (j * m_block_size); + bi.block_size = j < pi.blocks_in_piece - 1 ? block_size() + : piece_size - (j * block_size()); bool complete = bi.state == block_info::writing || bi.state == block_info::finished; if (i->info[j].peer == 0) @@ -4808,7 +4797,7 @@ namespace libtorrent else TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked); - TORRENT_ASSERT(m_block_size <= m_torrent_file->piece_length()); + TORRENT_ASSERT(block_size() <= m_torrent_file->piece_length()); } else { @@ -4840,8 +4829,8 @@ namespace libtorrent if (valid_metadata()) { - TORRENT_ASSERT(m_block_size > 0); - TORRENT_ASSERT((m_torrent_file->piece_length() & (m_block_size-1)) == 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); @@ -5080,8 +5069,8 @@ namespace libtorrent ptime now = time_now(); - int finished_time = total_seconds(m_finished_time); - int download_time = total_seconds(m_active_time) - finished_time; + int finished_time = m_finished_time; + int download_time = int(m_active_time) - finished_time; // if we haven't yet met the seed limits, set the seed_ratio_not_met // flag. That will make this seed prioritized @@ -5288,13 +5277,13 @@ namespace libtorrent for (std::vector::iterator i = m_trackers.begin() , end(m_trackers.end()); i != end; ++i) { - if (m_settings.announce_to_all_tiers + if (settings().announce_to_all_tiers && found_working && i->tier <= tier && tier != INT_MAX) continue; - if (i->tier > tier && !m_settings.announce_to_all_tiers) break; + if (i->tier > tier && !settings().announce_to_all_tiers) break; if (i->is_working()) { tier = i->tier; found_working = false; } if (i->fails >= i->fail_limit && i->fail_limit != 0) continue; if (i->updating) { found_working = true; continue; } @@ -5303,8 +5292,8 @@ namespace libtorrent ptime next_tracker_announce = (std::max)(i->next_announce, i->min_announce); if (!i->updating && next_tracker_announce < next_announce) next_announce = next_tracker_announce; found_working = true; - if (!m_settings.announce_to_all_trackers - && !m_settings.announce_to_all_tiers) break; + if (!settings().announce_to_all_trackers + && !settings().announce_to_all_tiers) break; } } if (next_announce == max_time()) return; @@ -5345,15 +5334,12 @@ namespace libtorrent if (!m_torrent_file->is_valid() || (!m_torrent_file->priv() && (!m_torrent_file->is_i2p() - || m_settings.allow_i2p_mixed))) + || settings().allow_i2p_mixed))) { if (m_ses.m_lsd) lsd_announce(); #ifndef TORRENT_DISABLE_DHT - error_code ec; - m_dht_announce_timer.expires_from_now(seconds(1), ec); - m_dht_announce_timer.async_wait( - bind(&torrent::on_dht_announce, shared_from_this(), _1)); + if (m_ses.m_dht) dht_announce(); #endif } } @@ -5363,9 +5349,6 @@ namespace libtorrent if (!m_announcing) return; error_code ec; -#ifndef TORRENT_DISABLE_DHT - m_dht_announce_timer.cancel(ec); -#endif m_tracker_timer.cancel(ec); m_announcing = false; @@ -5452,8 +5435,8 @@ namespace libtorrent // if we're in upload only mode and we're auto-managed // leave upload mode every 10 minutes hoping that the error // condition has been fixed - if (m_upload_mode && m_auto_managed && now - m_upload_mode_time - > seconds(m_settings.optimistic_disk_retry)) + if (m_upload_mode && m_auto_managed && m_upload_mode_time + >= settings().optimistic_disk_retry) { set_upload_mode(false); } @@ -5466,7 +5449,7 @@ namespace libtorrent return; } - if (m_settings.rate_limit_ip_overhead) + if (settings().rate_limit_ip_overhead) { int up_limit = m_bandwidth_channel[peer_connection::upload_channel].throttle(); int down_limit = m_bandwidth_channel[peer_connection::download_channel].throttle(); @@ -5488,10 +5471,14 @@ namespace libtorrent } } - time_duration since_last_tick = milliseconds(tick_interval_ms); - if (is_seed()) m_seeding_time += since_last_tick; - if (is_finished()) m_finished_time += since_last_tick; - m_active_time += since_last_tick; + int seconds_since_last_tick = 1; + if (m_ses.m_tick_residual >= 1000) ++seconds_since_last_tick; + + if (is_seed()) m_seeding_time += seconds_since_last_tick; + if (is_finished()) m_finished_time += seconds_since_last_tick; + if (m_upload_mode) m_upload_mode_time += seconds_since_last_tick; + m_last_scrape += seconds_since_last_tick; + m_active_time += seconds_since_last_tick; // ---- TIME CRITICAL PIECES ---- @@ -5558,7 +5545,7 @@ namespace libtorrent // rotate the cached pieces // add blocks_per_piece / 2 in order to round to closest whole piece - int blocks_per_piece = m_torrent_file->piece_length() / m_block_size; + int blocks_per_piece = m_torrent_file->piece_length() / block_size(); int num_cache_pieces = (cache_size + blocks_per_piece / 2) / blocks_per_piece; if (num_cache_pieces > m_torrent_file->num_pieces()) num_cache_pieces = m_torrent_file->num_pieces(); @@ -5640,7 +5627,7 @@ namespace libtorrent void torrent::get_suggested_pieces(std::vector& s) const { - if (m_ses.m_settings.suggest_mode == session_settings::no_piece_suggestions) + if (settings().suggest_mode == session_settings::no_piece_suggestions) { s.clear(); return; @@ -5664,7 +5651,7 @@ namespace libtorrent // if we have an explicit cache, it's much more likely to // stick around, so we should suggest all pieces int num_pieces_to_suggest = int(ret.size()); - if (!m_ses.m_settings.explicit_read_cache) + if (!settings().explicit_read_cache) num_pieces_to_suggest = (std::max)(1, int(ret.size() / 2)); ret.resize(num_pieces_to_suggest); @@ -5703,7 +5690,7 @@ namespace libtorrent , end(m_time_critical_pieces.end()); i != end; ++i) { if (i != m_time_critical_pieces.begin() && i->deadline > now - + m_average_piece_time + m_piece_time_deviation * 4) + + milliseconds(m_average_piece_time + m_piece_time_deviation * 4)) { // don't request pieces whose deadline is too far in the future break; @@ -5858,7 +5845,7 @@ namespace libtorrent f(ret); } - const tcp::endpoint& torrent::current_tracker() const + tcp::endpoint torrent::current_tracker() const { return m_tracker_address; } @@ -5954,7 +5941,7 @@ namespace libtorrent { TORRENT_ASSERT(file != m_torrent_file->end_files()); TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length() - + k * m_block_size); + + k * block_size()); TORRENT_ASSERT(offset < m_torrent_file->total_size()); while (offset >= file->offset + file->size) { @@ -5963,46 +5950,46 @@ namespace libtorrent } TORRENT_ASSERT(file != m_torrent_file->end_files()); - size_type block_size = m_block_size; + size_type block = block_size(); if (info[k].state == piece_picker::block_info::state_none) { - offset += m_block_size; + offset += block; continue; } if (info[k].state == piece_picker::block_info::state_requested) { - block_size = 0; + block = 0; policy::peer* p = static_cast(info[k].peer); if (p && p->connection) { boost::optional pbp = p->connection->downloading_piece_progress(); if (pbp && pbp->piece_index == i->index && pbp->block_index == k) - block_size = pbp->bytes_downloaded; - TORRENT_ASSERT(block_size <= m_block_size); + block = pbp->bytes_downloaded; + TORRENT_ASSERT(block <= block_size()); } - if (block_size == 0) + if (block == 0) { - offset += m_block_size; + offset += block_size(); continue; } } - if (offset + block_size > file->offset + file->size) + if (offset + block > file->offset + file->size) { - int left_over = m_block_size - block_size; + int left_over = block_size() - block; // split the block on multiple files - while (block_size > 0) + while (block > 0) { TORRENT_ASSERT(offset <= file->offset + file->size); size_type slice = (std::min)(file->offset + file->size - offset - , block_size); + , block); fp[file_index] += slice; offset += slice; - block_size -= slice; + block -= slice; TORRENT_ASSERT(offset <= file->offset + file->size); if (offset == file->offset + file->size) { @@ -6010,19 +5997,19 @@ namespace libtorrent ++file_index; if (file == m_torrent_file->end_files()) { - offset += block_size; + offset += block; break; } } } offset += left_over; TORRENT_ASSERT(offset == size_type(i->index) * m_torrent_file->piece_length() - + (k+1) * m_block_size); + + (k+1) * block_size()); } else { - fp[file_index] += block_size; - offset += m_block_size; + fp[file_index] += block; + offset += block_size(); } TORRENT_ASSERT(file_index <= m_torrent_file->num_files()); } @@ -6056,7 +6043,7 @@ namespace libtorrent if (m_state == s) return; if (m_ses.m_alerts.should_post()) - m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s, m_state)); + m_ses.m_alerts.post_alert(state_changed_alert(get_handle(), s, (torrent_status::state_t)m_state)); m_state = s; } @@ -6072,14 +6059,7 @@ namespace libtorrent if (m_error) st.error = m_error.message() + ": " + m_error_file; st.seed_mode = m_seed_mode; - if (m_last_scrape == min_time()) - { - st.last_scrape = -1; - } - else - { - st.last_scrape = total_seconds(now - m_last_scrape); - } + st.last_scrape = m_last_scrape; st.upload_mode = m_upload_mode; st.up_bandwidth_queue = 0; st.down_bandwidth_queue = 0; @@ -6091,16 +6071,16 @@ namespace libtorrent st.list_peers = m_policy.num_peers(); st.list_seeds = m_policy.num_seeds(); st.connect_candidates = m_policy.num_connect_candidates(); - st.seed_rank = seed_rank(m_ses.m_settings); + st.seed_rank = seed_rank(settings()); st.all_time_upload = m_total_uploaded; st.all_time_download = m_total_downloaded; - st.active_time = total_seconds(m_active_time); - st.active_time = total_seconds(m_active_time); - st.seeding_time = total_seconds(m_seeding_time); + st.active_time = m_active_time; + st.active_time = m_active_time; + st.seeding_time = m_seeding_time; - st.storage_mode = m_storage_mode; + st.storage_mode = (storage_mode_t)m_storage_mode; st.num_complete = m_complete; st.num_incomplete = m_incomplete; @@ -6159,7 +6139,7 @@ namespace libtorrent st.connections_limit = m_max_connections; // if we don't have any metadata, stop here - st.state = m_state; + st.state = (torrent_status::state_t)m_state; if (!valid_metadata()) { diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 8b4e4daf0..56ccb60b0 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -667,7 +667,7 @@ namespace libtorrent void torrent_handle::force_dht_announce() const { INVARIANT_CHECK; - TORRENT_FORWARD(force_dht_announce()); + TORRENT_FORWARD(dht_announce()); } #endif diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 347add880..1fc686878 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -207,7 +207,7 @@ namespace libtorrent void trim_path_element(std::string& path_element) { const int max_path_len = TORRENT_MAX_PATH; - if (path_element.size() > max_path_len) + if (int(path_element.size()) > max_path_len) { // truncate filenames that are too long. But keep extensions! std::string ext = extension(path_element);