diff --git a/libtorrent/include/libtorrent/assert.hpp b/libtorrent/include/libtorrent/assert.hpp new file mode 100644 index 000000000..488afe778 --- /dev/null +++ b/libtorrent/include/libtorrent/assert.hpp @@ -0,0 +1,55 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_ASSERT_HPP_INCLUDED +#define TORRENT_ASSERT_HPP_INCLUDED + +#ifndef NDEBUG +#if defined __linux__ && defined _GNUC +#ifdef assert +#undef assert +#endif + +void assert_fail(int line, char const* file); + +#define assert(x) if (!(x)) assert_fail(__LINE__, __FILE__) + +#endif + +#else +#ifndef assert +#define assert(x) (void) +#endif +#endif + +#endif + diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index bb3b41705..606a38930 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -244,8 +244,8 @@ namespace libtorrent , fs::path const& save_path , entry const& resume_data , bool compact_mode - , int block_size - , storage_constructor_type sc); + , storage_constructor_type sc + , bool paused); torrent_handle add_torrent( char const* tracker_url @@ -254,8 +254,8 @@ namespace libtorrent , fs::path const& save_path , entry const& resume_data , bool compact_mode - , int block_size - , storage_constructor_type sc); + , storage_constructor_type sc + , bool paused); void remove_torrent(torrent_handle const& h); @@ -493,7 +493,7 @@ namespace libtorrent // This implements a round robin. int m_next_connect_torrent; #ifndef NDEBUG - void check_invariant(const char *place = 0); + void check_invariant() const; #endif #ifdef TORRENT_STATS diff --git a/libtorrent/include/libtorrent/debug.hpp b/libtorrent/include/libtorrent/debug.hpp index 436b695f6..1bb645a8e 100755 --- a/libtorrent/include/libtorrent/debug.hpp +++ b/libtorrent/include/libtorrent/debug.hpp @@ -80,3 +80,4 @@ namespace libtorrent } #endif // TORRENT_DEBUG_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp index 15ad34a7a..82a4675e7 100755 --- a/libtorrent/include/libtorrent/peer_info.hpp +++ b/libtorrent/include/libtorrent/peer_info.hpp @@ -56,10 +56,11 @@ namespace libtorrent connecting = 0x80, queued = 0x100, on_parole = 0x200, - seed = 0x400 + seed = 0x400, + optimistic_unchoke = 0x800 #ifndef TORRENT_DISABLE_ENCRYPTION - , rc4_encrypted = 0x800, - plaintext_encrypted = 0x1000 + , rc4_encrypted = 0x100000, + plaintext_encrypted = 0x200000 #endif }; diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index a123314ed..7451f5915 100755 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -141,23 +141,9 @@ namespace libtorrent , fs::path const& save_path , entry const& resume_data = entry() , bool compact_mode = true - , int block_size = 16 * 1024 + , bool paused = false , storage_constructor_type sc = default_storage_constructor); - // ==== deprecated, this is for backwards compatibility only - // instead, use one of the other add_torrent overloads - torrent_handle add_torrent( - entry const& e - , fs::path const& save_path - , entry const& resume_data = entry() - , bool compact_mode = true - , int block_size = 16 * 1024 - , storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED - { - return add_torrent(torrent_info(e), save_path, resume_data - , compact_mode, block_size, sc); - } - torrent_handle add_torrent( char const* tracker_url , sha1_hash const& info_hash @@ -165,7 +151,7 @@ namespace libtorrent , fs::path const& save_path , entry const& resume_data = entry() , bool compact_mode = true - , int block_size = 16 * 1024 + , bool paused = false , storage_constructor_type sc = default_storage_constructor); session_proxy abort() { return session_proxy(m_impl); } diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 6781465c0..dabc34141 100755 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -102,8 +102,8 @@ namespace libtorrent , tcp::endpoint const& net_interface , bool compact_mode , int block_size - , session_settings const& s - , storage_constructor_type sc); + , storage_constructor_type sc + , bool paused); // used with metadata-less torrents // (the metadata is downloaded from the peers) @@ -117,8 +117,8 @@ namespace libtorrent , tcp::endpoint const& net_interface , bool compact_mode , int block_size - , session_settings const& s - , storage_constructor_type sc); + , storage_constructor_type sc + , bool paused); ~torrent(); diff --git a/libtorrent/src/assert.cpp b/libtorrent/src/assert.cpp new file mode 100644 index 000000000..c2cb1b4a5 --- /dev/null +++ b/libtorrent/src/assert.cpp @@ -0,0 +1,60 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef NDEBUG + +#include + +void assert_fail(int line, char const* file) +{ + + fprintf(stderr, "assertion failed. Please file a bugreport at " + "http://code.rasterbar.com/libtorrent/newticket\n" + "Please include the following information:\n\n" + "file: '%s'\n" + "line: %d\n" + "stack:\n", file, line); + + void* stacktrace[50]; + int size = backtrace(stack, 50); + char** symbols = backtrace_symbols(stack, size); + + for (int i = 0; i < size; ++i) + { + fprintf(stderr, "%d: %s\n", i, symbols[i]); + } + + free(symbols); +} + +#endif + diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp index 97635cdb9..a19dd3d3f 100644 --- a/libtorrent/src/metadata_transfer.cpp +++ b/libtorrent/src/metadata_transfer.cpp @@ -523,7 +523,7 @@ namespace libtorrent { namespace if (num_blocks < 1) num_blocks = 1; assert(num_blocks <= 128); - int min_element = std::numeric_limits::max(); + int min_element = (std::numeric_limits::max)(); int best_index = 0; for (int i = 0; i < 256 - num_blocks + 1; ++i) { diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 4ee8b93e7..6bc604bab 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -1480,7 +1480,7 @@ namespace libtorrent assert(!m_have_piece.empty()); std::fill(m_have_piece.begin(), m_have_piece.end(), true); - m_num_pieces = m_have_piece.size(); + m_num_pieces = m_have_piece.size(); t->peer_has_all(); if (!t->is_finished()) @@ -1563,13 +1563,9 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); assert(t); - for (std::vector::iterator i = m_allowed_fast.begin() - , end(m_allowed_fast.end()); i != end; ++i) - { - if (!t->have_piece(*i)) continue; - *i = m_allowed_fast.back(); - m_allowed_fast.pop_back(); - } + m_allowed_fast.erase(std::remove_if(m_allowed_fast.begin() + , m_allowed_fast.end(), bind(&torrent::have_piece, t, _1)) + , m_allowed_fast.end()); // TODO: sort the allowed fast set in priority order return m_allowed_fast; @@ -1683,6 +1679,8 @@ namespace libtorrent { INVARIANT_CHECK; + assert(!m_peer_info || !m_peer_info->optimistically_unchoked); + if (m_choked) return; write_choke(); m_choked = true; @@ -1701,14 +1699,6 @@ namespace libtorrent { INVARIANT_CHECK; -#ifndef NDEBUG - // TODO: once the policy lowers the interval for optimistic - // unchoke, increase this value that interval - // this condition cannot be guaranteed since if peers disconnect - // a new one will be unchoked ignoring when it was last choked - //assert(time_now() - m_last_choke > seconds(9)); -#endif - if (!m_choked) return; write_unchoke(); m_choked = false; @@ -1904,7 +1894,7 @@ namespace libtorrent void peer_connection::set_upload_limit(int limit) { assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); + if (limit == -1) limit = (std::numeric_limits::max)(); if (limit < 10) limit = 10; m_upload_limit = limit; m_bandwidth_limit[upload_channel].throttle(m_upload_limit); @@ -1913,7 +1903,7 @@ namespace libtorrent void peer_connection::set_download_limit(int limit) { assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); + if (limit == -1) limit = (std::numeric_limits::max)(); if (limit < 10) limit = 10; m_download_limit = limit; m_bandwidth_limit[download_channel].throttle(m_download_limit); @@ -1931,7 +1921,7 @@ namespace libtorrent // if we have an infinite ratio, just say we have downloaded // much more than we have uploaded. And we'll keep uploading. if (ratio == 0.f) - return std::numeric_limits::max(); + return (std::numeric_limits::max)(); return m_free_upload + static_cast(m_statistics.total_payload_download() * ratio) @@ -2013,6 +2003,7 @@ namespace libtorrent p.failcount = peer_info_struct()->failcount; p.num_hashfails = peer_info_struct()->hashfails; p.flags |= peer_info_struct()->on_parole ? peer_info::on_parole : 0; + p.flags |= peer_info_struct()->optimistically_unchoked ? peer_info::optimistic_unchoke : 0; p.remote_dl_rate = m_remote_dl_rate; } else @@ -2171,7 +2162,7 @@ namespace libtorrent + bias) / break_even_time, double(m_upload_limit)); upload_speed_limit = (std::min)(upload_speed_limit, - (double)std::numeric_limits::max()); + (double)(std::numeric_limits::max)()); m_bandwidth_limit[upload_channel].throttle( (std::min)((std::max)((int)upload_speed_limit, 20) @@ -2235,20 +2226,6 @@ namespace libtorrent m_reading_bytes += r.length; m_requests.erase(m_requests.begin()); -/* - if (m_requests.empty() - && m_num_invalid_requests > 0 - && is_peer_interested() - && !is_seed()) - { - // this will make the peer clear - // its download queue and re-request - // pieces. Hopefully it will not - // send invalid requests then - send_choke(); - send_unchoke(); - } -*/ } } @@ -2789,9 +2766,14 @@ namespace libtorrent void peer_connection::check_invariant() const { if (m_peer_info) + { assert(m_peer_info->connection == this || m_peer_info->connection == 0); - + + if (m_peer_info->optimistically_unchoked) + assert(!is_choked()); + } + boost::shared_ptr t = m_torrent.lock(); if (!t) { diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 7f44d600c..d326b43bb 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -394,6 +394,7 @@ namespace libtorrent assert(!t->have_piece(index)); int prio = i->priority(m_sequenced_download_threshold); + assert(prio < int(m_piece_info.size())); if (prio > 0) { const std::vector& vec = m_piece_info[prio]; @@ -739,6 +740,7 @@ namespace libtorrent , end(m_piece_map.end()); i != end; ++i) { int prev_prio = i->priority(m_sequenced_download_threshold); + assert(prev_prio < int(m_piece_info.size())); ++i->peer_count; // if the assumption that the priority would // increase by 2 when increasing the availability @@ -828,6 +830,8 @@ namespace libtorrent , end(m_piece_map.end()); i != end; ++i) { int prev_prio = i->priority(m_sequenced_download_threshold); + assert(prev_prio < int(m_piece_info.size())); + assert(pushed_out_index < int(m_piece_info.size())); assert(i->peer_count > 0); --i->peer_count; // if the assumption that the priority would @@ -879,6 +883,7 @@ namespace libtorrent piece_pos& p = m_piece_map[i]; int index = p.index; int prev_priority = p.priority(m_sequenced_download_threshold); + assert(prev_priority < int(m_piece_info.size())); assert(p.peer_count < piece_pos::max_peer_count); p.peer_count++; @@ -913,6 +918,7 @@ namespace libtorrent piece_pos& p = m_piece_map[i]; int prev_priority = p.priority(m_sequenced_download_threshold); + assert(prev_priority < int(m_piece_info.size())); int index = p.index; assert(p.peer_count > 0); @@ -937,6 +943,7 @@ namespace libtorrent piece_pos& p = m_piece_map[index]; int info_index = p.index; int priority = p.priority(m_sequenced_download_threshold); + assert(priority < int(m_piece_info.size())); assert(p.downloading == 1); assert(!p.have()); @@ -980,6 +987,7 @@ namespace libtorrent if (new_piece_priority == int(p.piece_priority)) return false; int prev_priority = p.priority(m_sequenced_download_threshold); + assert(prev_priority < int(m_piece_info.size())); bool ret = false; if (new_piece_priority == piece_pos::filter_priority @@ -1003,6 +1011,7 @@ namespace libtorrent p.piece_priority = new_piece_priority; int new_priority = p.priority(m_sequenced_download_threshold); + assert(prev_priority < int(m_piece_info.size())); if (new_priority == prev_priority) return false; @@ -1224,6 +1233,9 @@ namespace libtorrent // skip it if (!pieces[*i]) continue; + // skip the piece is the priority is 0 + if (m_piece_map[*i].priority(m_sequenced_download_threshold) == 0) continue; + int num_blocks_in_piece = blocks_in_piece(*i); if (m_piece_map[*i].downloading == 1) @@ -1419,6 +1431,7 @@ namespace libtorrent if (p.downloading == 0) { int prio = p.priority(m_sequenced_download_threshold); + assert(prio < int(m_piece_info.size())); assert(prio > 0); p.downloading = 1; move(prio, p.index); @@ -1530,6 +1543,7 @@ namespace libtorrent assert(peer == 0); int prio = p.priority(m_sequenced_download_threshold); + assert(prio < int(m_piece_info.size())); p.downloading = 1; if (prio > 0) move(prio, p.index); else assert(p.priority(m_sequenced_download_threshold) == 0); @@ -1652,6 +1666,7 @@ namespace libtorrent erase_download_piece(i); piece_pos& p = m_piece_map[block.piece_index]; int prio = p.priority(m_sequenced_download_threshold); + assert(prio < int(m_piece_info.size())); p.downloading = 0; if (prio > 0) move(prio, p.index); diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index 4f2e6211a..e92addcb4 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -83,7 +83,7 @@ namespace // (and we should not consider it free). If the share diff is // negative, there's no free download to get from this peer. size_type diff = i->second->share_diff(); - assert(diff < std::numeric_limits::max()); + assert(diff < (std::numeric_limits::max)()); if (i->second->is_peer_interested() || diff <= 0) continue; @@ -110,7 +110,7 @@ namespace for (torrent::peer_iterator i = start; i != end; ++i) { size_type d = i->second->share_diff(); - assert(d < std::numeric_limits::max()); + assert(d < (std::numeric_limits::max)()); total_diff += d; if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue; ++num_peers; @@ -120,7 +120,7 @@ namespace size_type upload_share; if (total_diff >= 0) { - upload_share = std::min(free_upload, total_diff) / num_peers; + upload_share = (std::min)(free_upload, total_diff) / num_peers; } else { @@ -280,6 +280,7 @@ namespace libtorrent { if (p.is_requested(*i)) { + if (num_requests <= 0) break; // don't request pieces we already have in our request queue const std::deque& dq = c.download_queue(); const std::deque& rq = c.request_queue(); @@ -299,10 +300,9 @@ namespace libtorrent assert(p.num_peers(*i) == 1); assert(p.is_requested(*i)); num_requests--; - if (num_requests == 0) break; } - if (busy_pieces.empty() || num_requests == 0) + if (busy_pieces.empty() || num_requests <= 0) { // in this case, we could not find any blocks // that was free. If we couldn't find any busy @@ -385,7 +385,7 @@ namespace libtorrent INVARIANT_CHECK; iterator worst_peer = m_peers.end(); - size_type min_weight = std::numeric_limits::min(); + size_type min_weight = (std::numeric_limits::min)(); #ifndef NDEBUG int unchoked_counter = m_num_unchoked; @@ -464,7 +464,7 @@ namespace libtorrent INVARIANT_CHECK; iterator disconnect_peer = m_peers.end(); - double slowest_transfer_rate = std::numeric_limits::max(); + double slowest_transfer_rate = (std::numeric_limits::max)(); ptime now = time_now(); @@ -693,7 +693,7 @@ namespace libtorrent ++num_connected_peers; } - if (m_torrent->max_connections() != std::numeric_limits::max()) + if (m_torrent->max_connections() != (std::numeric_limits::max)()) { int max_connections = m_torrent->max_connections(); @@ -1215,7 +1215,7 @@ namespace libtorrent if (m_torrent->ratio() != 0.f) { - assert(c.share_diff() < std::numeric_limits::max()); + assert(c.share_diff() < (std::numeric_limits::max)()); size_type diff = c.share_diff(); if (diff > 0 && c.is_seed()) { @@ -1320,14 +1320,16 @@ namespace libtorrent INVARIANT_CHECK; peer* p = c.peer_info_struct(); - // if we couldn't find the connection in our list, just ignore it. - if (p == 0) return; - assert(std::find_if( + assert((std::find_if( m_peers.begin() , m_peers.end() , match_peer_connection(c)) - != m_peers.end()); + != m_peers.end()) == (p != 0)); + + // if we couldn't find the connection in our list, just ignore it. + if (p == 0) return; + assert(p->connection == &c); p->connection = 0; @@ -1347,7 +1349,7 @@ namespace libtorrent if (m_torrent->ratio() != 0.f) { assert(c.associated_torrent().lock().get() == m_torrent); - assert(c.share_diff() < std::numeric_limits::max()); + assert(c.share_diff() < (std::numeric_limits::max)()); m_available_free_upload += c.share_diff(); } p->prev_amount_download += c.statistics().total_payload_download(); @@ -1368,10 +1370,12 @@ namespace libtorrent #ifndef NDEBUG bool policy::has_connection(const peer_connection* c) { - INVARIANT_CHECK; +// too expensive +// INVARIANT_CHECK; assert(c); - assert(c->remote() == c->get_socket()->remote_endpoint()); + try { assert(c->remote() == c->get_socket()->remote_endpoint()); } + catch (std::exception&) {} return std::find_if( m_peers.begin() @@ -1405,6 +1409,11 @@ namespace libtorrent , boost::bind(std::equal_to(), _1, p.connection)) != conns.end()); } + if (p.optimistically_unchoked) + { + assert(p.connection); + assert(!p.connection->is_choked()); + } assert(p.connection->peer_info_struct() == 0 || p.connection->peer_info_struct() == &p); ++nonempty_connections; diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 6d6fa55b2..8175cbdfe 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -179,11 +179,11 @@ namespace libtorrent , fs::path const& save_path , entry const& resume_data , bool compact_mode - , int block_size + , bool paused , storage_constructor_type sc) { return m_impl->add_torrent(ti, save_path, resume_data - , compact_mode, block_size, sc); + , compact_mode, sc, paused); } torrent_handle session::add_torrent( @@ -193,11 +193,11 @@ namespace libtorrent , fs::path const& save_path , entry const& e , bool compact_mode - , int block_size + , bool paused , storage_constructor_type sc) { return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e - , compact_mode, block_size, sc); + , compact_mode, sc, paused); } void session::remove_torrent(const torrent_handle& h) diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index a77b60c9c..d20cf9668 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -624,6 +624,9 @@ namespace detail void session_impl::set_ip_filter(ip_filter const& f) { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + m_ip_filter = f; // Close connections whose endpoint is filtered @@ -636,6 +639,9 @@ namespace detail void session_impl::set_settings(session_settings const& s) { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + assert(s.connection_speed > 0); assert(s.file_pool_size > 0); @@ -802,6 +808,9 @@ namespace detail #endif { mutex_t::scoped_lock l(m_mutex); + +// too expensive +// INVARIANT_CHECK; connection_map::iterator p = m_connections.find(s); @@ -833,6 +842,9 @@ namespace detail { mutex_t::scoped_lock l(m_mutex); +// too expensive +// INVARIANT_CHECK; + assert(p->is_disconnecting()); connection_map::iterator i = m_connections.find(p->get_socket()); if (i != m_connections.end()) @@ -858,6 +870,8 @@ namespace detail { session_impl::mutex_t::scoped_lock l(m_mutex); + INVARIANT_CHECK; + if (e) { #if defined(TORRENT_LOGGING) @@ -1106,8 +1120,11 @@ namespace detail } else { + assert(p->peer_info_struct()); if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked) t->choke_peer(*p); + if (!p->is_choked()) + ++m_num_unchoked; } } @@ -1135,6 +1152,7 @@ namespace detail if (pi->optimistically_unchoked) { + assert(!p->is_choked()); assert(current_optimistic_unchoke == m_connections.end()); current_optimistic_unchoke = i; } @@ -1158,8 +1176,12 @@ namespace detail { torrent* t = current_optimistic_unchoke->second->associated_torrent().lock().get(); assert(t); - t->choke_peer(*current_optimistic_unchoke->second); current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false; + t->choke_peer(*current_optimistic_unchoke->second); + } + else + { + ++m_num_unchoked; } torrent* t = optimistic_unchoke_candidate->second->associated_torrent().lock().get(); @@ -1168,9 +1190,6 @@ namespace detail assert(ret); optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true; } - - if (optimistic_unchoke_candidate != m_connections.end()) - ++m_num_unchoked; } } @@ -1428,25 +1447,12 @@ namespace detail , fs::path const& save_path , entry const& resume_data , bool compact_mode - , int block_size - , storage_constructor_type sc) + , storage_constructor_type sc + , bool paused) { // if you get this assert, you haven't managed to // open a listen port. call listen_on() first. assert(m_external_listen_port > 0); - - // make sure the block_size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (block_size & (1 << i)) - { - assert((block_size & ~(1 << i)) == 0); - break; - } - } -#endif - assert(!save_path.empty()); if (ti.begin_files() == ti.end_files()) @@ -1456,6 +1462,8 @@ namespace detail mutex_t::scoped_lock l(m_mutex); mutex::scoped_lock l2(m_checker_impl.m_mutex); + INVARIANT_CHECK; + if (is_aborted()) throw std::runtime_error("session is closing"); @@ -1472,8 +1480,8 @@ namespace detail // the thread boost::shared_ptr torrent_ptr( new torrent(*this, m_checker_impl, ti, save_path - , m_listen_interface, compact_mode, block_size - , settings(), sc)); + , m_listen_interface, compact_mode, 16 * 1024 + , sc, paused)); torrent_ptr->start(); #ifndef TORRENT_DISABLE_EXTENSIONS @@ -1519,20 +1527,9 @@ namespace detail , fs::path const& save_path , entry const& , bool compact_mode - , int block_size - , storage_constructor_type sc) + , storage_constructor_type sc + , bool paused) { - // make sure the block_size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (block_size & (1 << i)) - { - assert((block_size & ~(1 << i)) == 0); - break; - } - } -#endif // TODO: support resume data in this case assert(!save_path.empty()); @@ -1548,6 +1545,8 @@ namespace detail // lock the session session_impl::mutex_t::scoped_lock l(m_mutex); + INVARIANT_CHECK; + // is the torrent already active? if (!find_torrent(info_hash).expired()) throw duplicate_torrent(); @@ -1560,8 +1559,8 @@ namespace detail // the thread boost::shared_ptr torrent_ptr( new torrent(*this, m_checker_impl, tracker_url, info_hash, name - , save_path, m_listen_interface, compact_mode, block_size - , settings(), sc)); + , save_path, m_listen_interface, compact_mode, 16 * 1024 + , sc, paused)); torrent_ptr->start(); #ifndef TORRENT_DISABLE_EXTENSIONS @@ -1586,6 +1585,9 @@ namespace detail assert(h.m_ses != 0); mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + session_impl::torrent_map::iterator i = m_torrents.find(h.m_info_hash); if (i != m_torrents.end()) @@ -1648,6 +1650,8 @@ namespace detail { session_impl::mutex_t::scoped_lock l(m_mutex); + INVARIANT_CHECK; + tcp::endpoint new_interface; if (net_interface && std::strlen(net_interface) > 0) new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first); @@ -1727,6 +1731,8 @@ namespace detail { mutex_t::scoped_lock l(m_mutex); + INVARIANT_CHECK; + boost::shared_ptr t = find_torrent(ih).lock(); if (!t) return; // don't add peers from lsd to private torrents @@ -1781,6 +1787,9 @@ namespace detail session_status session_impl::status() const { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + session_status s; s.has_incoming_connections = m_incoming_connection; s.num_peers = (int)m_connections.size(); @@ -1822,6 +1831,9 @@ namespace detail void session_impl::start_dht(entry const& startup_state) { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + if (m_dht) { m_dht->stop(); @@ -1981,7 +1993,10 @@ namespace detail { assert(limit > 0 || limit == -1); mutex_t::scoped_lock l(m_mutex); - if (limit <= 0) limit = std::numeric_limits::max(); + + INVARIANT_CHECK; + + if (limit <= 0) limit = (std::numeric_limits::max)(); m_max_uploads = limit; } @@ -1989,7 +2004,10 @@ namespace detail { assert(limit > 0 || limit == -1); mutex_t::scoped_lock l(m_mutex); - if (limit <= 0) limit = std::numeric_limits::max(); + + INVARIANT_CHECK; + + if (limit <= 0) limit = (std::numeric_limits::max)(); m_max_connections = limit; } @@ -1997,7 +2015,10 @@ namespace detail { assert(limit > 0 || limit == -1); mutex_t::scoped_lock l(m_mutex); - if (limit <= 0) limit = std::numeric_limits::max(); + + INVARIANT_CHECK; + + if (limit <= 0) limit = (std::numeric_limits::max)(); m_half_open.limit(limit); } @@ -2005,6 +2026,9 @@ namespace detail { assert(bytes_per_second > 0 || bytes_per_second == -1); mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf; m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second); } @@ -2013,6 +2037,9 @@ namespace detail { assert(bytes_per_second > 0 || bytes_per_second == -1); mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf; m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second); } @@ -2020,6 +2047,10 @@ namespace detail std::auto_ptr session_impl::pop_alert() { mutex_t::scoped_lock l(m_mutex); + +// too expensive +// INVARIANT_CHECK; + if (m_alerts.pending()) return m_alerts.get(); return std::auto_ptr(0); @@ -2034,20 +2065,26 @@ namespace detail int session_impl::upload_rate_limit() const { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); - return ret == std::numeric_limits::max() ? -1 : ret; + return ret == (std::numeric_limits::max)() ? -1 : ret; } int session_impl::download_rate_limit() const { mutex_t::scoped_lock l(m_mutex); int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle(); - return ret == std::numeric_limits::max() ? -1 : ret; + return ret == (std::numeric_limits::max)() ? -1 : ret; } void session_impl::start_lsd() { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + m_lsd.reset(new lsd(m_io_service , m_listen_interface.address() , bind(&session_impl::on_lsd_peer, this, _1, _2))); @@ -2056,6 +2093,9 @@ namespace detail void session_impl::start_natpmp() { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + m_natpmp.reset(new natpmp(m_io_service , m_listen_interface.address() , bind(&session_impl::on_port_mapping @@ -2071,6 +2111,9 @@ namespace detail void session_impl::start_upnp() { mutex_t::scoped_lock l(m_mutex); + + INVARIANT_CHECK; + m_upnp.reset(new upnp(m_io_service, m_half_open , m_listen_interface.address() , m_settings.user_agent @@ -2108,14 +2151,13 @@ namespace detail #ifndef NDEBUG - void session_impl::check_invariant(const char *place) + void session_impl::check_invariant() const { assert(m_max_connections > 0); assert(m_max_uploads > 0); - assert(place); int unchokes = 0; int num_optimistic = 0; - for (connection_map::iterator i = m_connections.begin(); + for (connection_map::const_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { assert(i->second); @@ -2124,14 +2166,20 @@ namespace detail if (!i->second->is_choked()) ++unchokes; if (i->second->peer_info_struct() && i->second->peer_info_struct()->optimistically_unchoked) + { ++num_optimistic; - if (t) + assert(!i->second->is_choked()); + } + if (t && i->second->peer_info_struct()) { assert(t->get_policy().has_connection(boost::get_pointer(i->second))); } } assert(num_optimistic == 0 || num_optimistic == 1); - assert(m_num_unchoked == unchokes); + if (m_num_unchoked != unchokes) + { + assert(false); + } } #endif diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 8b977f0a2..a425a8f51 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -155,11 +155,11 @@ namespace libtorrent , tcp::endpoint const& net_interface , bool compact_mode , int block_size - , session_settings const& s - , storage_constructor_type sc) + , storage_constructor_type sc + , bool paused) : m_torrent_file(tf) , m_abort(false) - , m_paused(false) + , m_paused(paused) , m_just_paused(false) , m_event(tracker_request::started) , m_block_size(0) @@ -197,11 +197,11 @@ namespace libtorrent , m_compact_mode(compact_mode) , m_default_block_size(block_size) , m_connections_initialized(true) - , m_settings(s) + , m_settings(ses.settings()) , m_storage_constructor(sc) - , m_max_uploads(std::numeric_limits::max()) + , m_max_uploads((std::numeric_limits::max)()) , m_num_uploads(0) - , m_max_connections(std::numeric_limits::max()) + , m_max_connections((std::numeric_limits::max)()) { #ifndef NDEBUG m_initial_done = 0; @@ -219,11 +219,11 @@ namespace libtorrent , tcp::endpoint const& net_interface , bool compact_mode , int block_size - , session_settings const& s - , storage_constructor_type sc) + , storage_constructor_type sc + , bool paused) : m_torrent_file(info_hash) , m_abort(false) - , m_paused(false) + , m_paused(paused) , m_just_paused(false) , m_event(tracker_request::started) , m_block_size(0) @@ -260,11 +260,11 @@ namespace libtorrent , m_compact_mode(compact_mode) , m_default_block_size(block_size) , m_connections_initialized(false) - , m_settings(s) + , m_settings(ses.settings()) , m_storage_constructor(sc) - , m_max_uploads(std::numeric_limits::max()) + , m_max_uploads((std::numeric_limits::max)()) , m_num_uploads(0) - , m_max_connections(std::numeric_limits::max()) + , m_max_connections((std::numeric_limits::max)()) { #ifndef NDEBUG m_initial_done = 0; @@ -2459,14 +2459,14 @@ namespace libtorrent void torrent::set_max_uploads(int limit) { assert(limit >= -1); - if (limit <= 0) limit = std::numeric_limits::max(); + if (limit <= 0) limit = (std::numeric_limits::max)(); m_max_uploads = limit; } void torrent::set_max_connections(int limit) { assert(limit >= -1); - if (limit <= 0) limit = std::numeric_limits::max(); + if (limit <= 0) limit = (std::numeric_limits::max)(); m_max_connections = limit; } @@ -2489,7 +2489,7 @@ namespace libtorrent void torrent::set_upload_limit(int limit) { assert(limit >= -1); - if (limit <= 0) limit = std::numeric_limits::max(); + if (limit <= 0) limit = (std::numeric_limits::max)(); if (limit < num_peers() * 10) limit = num_peers() * 10; m_bandwidth_limit[peer_connection::upload_channel].throttle(limit); } @@ -2497,14 +2497,14 @@ namespace libtorrent int torrent::upload_limit() const { int limit = m_bandwidth_limit[peer_connection::upload_channel].throttle(); - if (limit == std::numeric_limits::max()) limit = -1; + if (limit == (std::numeric_limits::max)()) limit = -1; return limit; } void torrent::set_download_limit(int limit) { assert(limit >= -1); - if (limit <= 0) limit = std::numeric_limits::max(); + if (limit <= 0) limit = (std::numeric_limits::max)(); if (limit < num_peers() * 10) limit = num_peers() * 10; m_bandwidth_limit[peer_connection::download_channel].throttle(limit); } @@ -2512,7 +2512,7 @@ namespace libtorrent int torrent::download_limit() const { int limit = m_bandwidth_limit[peer_connection::download_channel].throttle(); - if (limit == std::numeric_limits::max()) limit = -1; + if (limit == (std::numeric_limits::max)()) limit = -1; return limit; } diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index 4ea09aefd..e43f3f297 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -674,7 +674,7 @@ namespace libtorrent { assert(m_piece_length > 0); - if ((m_urls.empty() && m_nodes.empty()) || m_files.empty()) + if (m_files.empty()) { // TODO: throw something here // throw diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp index efd9633e7..cddb35e42 100755 --- a/libtorrent/src/web_peer_connection.cpp +++ b/libtorrent/src/web_peer_connection.cpp @@ -510,7 +510,7 @@ namespace libtorrent // m_piece as buffer. int piece_size = int(m_piece.size()); - int copy_size = (std::min)(std::min(front_request.length - piece_size + int copy_size = (std::min)((std::min)(front_request.length - piece_size , recv_buffer.left()), int(range_end - range_start - m_received_body)); m_piece.resize(piece_size + copy_size); assert(copy_size > 0); @@ -568,7 +568,7 @@ namespace libtorrent && (m_received_body + recv_buffer.left() >= range_end - range_start)) { int piece_size = int(m_piece.size()); - int copy_size = (std::min)(std::min(m_requests.front().length - piece_size + int copy_size = (std::min)((std::min)(m_requests.front().length - piece_size , recv_buffer.left()), int(range_end - range_start - m_received_body)); assert(copy_size >= 0); if (copy_size > 0)