From a69be4161bd205d6c7d0aad3ad7db2cb6920dd6c Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Fri, 3 Aug 2007 08:25:15 +0000 Subject: [PATCH] libtorrent sync 1427 --- .../include/libtorrent/disk_io_thread.hpp | 4 ++ .../include/libtorrent/peer_connection.hpp | 7 +- .../include/libtorrent/piece_picker.hpp | 3 + .../include/libtorrent/session_settings.hpp | 2 +- libtorrent/src/Makefile.am | 2 +- libtorrent/src/disk_io_thread.cpp | 5 ++ libtorrent/src/peer_connection.cpp | 23 ++++++- libtorrent/src/piece_picker.cpp | 68 ++++++++++++------- libtorrent/src/policy.cpp | 12 +++- libtorrent/src/storage.cpp | 1 + libtorrent/src/web_peer_connection.cpp | 9 ++- 11 files changed, 99 insertions(+), 37 deletions(-) diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index aff0930e4..16ee0bca4 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -111,6 +111,10 @@ namespace libtorrent // memory pool for read and write operations boost::pool<> m_pool; +#ifndef NDEBUG + int m_block_size; +#endif + // thread for performing blocking disk io operations boost::thread m_disk_io_thread; }; diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp index caac2f63c..31bcde94a 100755 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -391,9 +391,7 @@ namespace libtorrent #ifndef TORRENT_DISABLE_ENCRYPTION buffer::interval wr_recv_buffer() { -#if defined _SECURE_SCL && _SECURE_SCL > 0 if (m_recv_buffer.empty()) return buffer::interval(0,0); -#endif return buffer::interval(&m_recv_buffer[0] , &m_recv_buffer[0] + m_recv_pos); } @@ -401,9 +399,7 @@ namespace libtorrent buffer::const_interval receive_buffer() const { -#if defined _SECURE_SCL && _SECURE_SCL > 0 if (m_recv_buffer.empty()) return buffer::const_interval(0,0); -#endif return buffer::const_interval(&m_recv_buffer[0] , &m_recv_buffer[0] + m_recv_pos); } @@ -642,7 +638,8 @@ namespace libtorrent bool m_queued; // these are true when there's a asynchronous write - // or read operation running. + // or read operation in progress. Or an asyncronous bandwidth + // request is in progress. bool m_writing; bool m_reading; diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp index 136e71c63..9595e2501 100755 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ b/libtorrent/include/libtorrent/piece_picker.hpp @@ -215,6 +215,9 @@ namespace libtorrent void mark_as_finished(piece_block block, void* peer); int num_peers(piece_block block) const; + // returns information about the given piece + void piece_info(int index, piece_picker::downloading_piece& st) const; + // if a piece had a hash-failure, it must be restored and // made available for redownloading void restore_piece(int index); diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 1aef3f199..ebc30eae3 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -108,7 +108,7 @@ namespace libtorrent , unchoke_interval(20) , num_want(200) , initial_picker_threshold(4) - , max_outstanding_disk_bytes_per_connection(128 * 1024) + , max_outstanding_disk_bytes_per_connection(64 * 1024) #ifndef TORRENT_DISABLE_DHT , use_dht_as_fallback(true) #endif diff --git a/libtorrent/src/Makefile.am b/libtorrent/src/Makefile.am index ef834018b..fabe68b65 100644 --- a/libtorrent/src/Makefile.am +++ b/libtorrent/src/Makefile.am @@ -95,6 +95,6 @@ $(top_srcdir)/include/libtorrent/version.hpp libtorrent_la_LDFLAGS = $(LDFLAGS) -release @VERSION@ libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ -AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@ +AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@ -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION AM_LDFLAGS= $(LDFLAGS) -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index b02ab0012..6bc357506 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -41,6 +41,9 @@ namespace libtorrent : m_abort(false) , m_queue_buffer_size(0) , m_pool(block_size) +#ifndef NDEBUG + , m_block_size(block_size) +#endif , m_disk_io_thread(boost::ref(*this)) {} @@ -192,6 +195,7 @@ namespace libtorrent } else { + assert(j.buffer_size <= m_block_size); ret = j.storage->read_impl(j.buffer, j.piece, j.offset , j.buffer_size); @@ -201,6 +205,7 @@ namespace libtorrent break; case disk_io_job::write: assert(j.buffer); + assert(j.buffer_size <= m_block_size); j.storage->write_impl(j.buffer, j.piece, j.offset , j.buffer_size); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index a0c4cc21c..8666e4236 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -1153,6 +1153,7 @@ namespace libtorrent fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete , self(), _1, _2, p, t)); m_outstanding_writing_bytes += p.length; + assert(!m_reading); picker.mark_as_writing(block_finished, peer_info_struct()); } @@ -1164,6 +1165,9 @@ namespace libtorrent m_outstanding_writing_bytes -= p.length; assert(m_outstanding_writing_bytes >= 0); +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << " *** on_disk_write_complete() " << p.length << "\n"; +#endif // in case the outstanding bytes just dropped down // to allow to receive more data setup_receive(); @@ -2049,11 +2053,13 @@ namespace libtorrent m_bandwidth_limit[channel].assign(amount); if (channel == upload_channel) { + assert(m_writing); m_writing = false; setup_send(); } else if (channel == download_channel) { + assert(m_reading); m_reading = false; setup_receive(); } @@ -2101,10 +2107,11 @@ namespace libtorrent (*m_logger) << "req bandwidth [ " << upload_channel << " ]\n"; #endif + assert(!m_writing); // peers that we are not interested in are non-prioritized + m_writing = true; t->request_bandwidth(upload_channel, self() , !(is_interesting() && !has_peer_choked())); - m_writing = true; } return; } @@ -2150,6 +2157,9 @@ namespace libtorrent INVARIANT_CHECK; +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << "setup_receive: reading = " << m_reading << "\n"; +#endif if (m_reading) return; shared_ptr t = m_torrent.lock(); @@ -2164,8 +2174,8 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "req bandwidth [ " << download_channel << " ]\n"; #endif - t->request_bandwidth(download_channel, self(), m_non_prioritized); m_reading = true; + t->request_bandwidth(download_channel, self(), m_non_prioritized); } return; } @@ -2353,11 +2363,17 @@ namespace libtorrent { INVARIANT_CHECK; - return (m_bandwidth_limit[download_channel].quota_left() > 0 + bool ret = (m_bandwidth_limit[download_channel].quota_left() > 0 || m_ignore_bandwidth_limits) && !m_connecting && m_outstanding_writing_bytes < m_ses.settings().max_outstanding_disk_bytes_per_connection; + +#if defined(TORRENT_VERBOSE_LOGGING) + (*m_logger) << "*** can_read() " << ret << " reading: " << m_reading << "\n"; +#endif + + return ret; } void peer_connection::connect(int ticket) @@ -2682,6 +2698,7 @@ namespace libtorrent (*m_logger) << time_now_string() << " ==> KEEPALIVE\n"; #endif + m_last_sent = time_now(); write_keepalive(); } diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 7691bd384..833ceb793 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -129,6 +129,35 @@ namespace libtorrent } } + void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const + { + TORRENT_PIECE_PICKER_INVARIANT_CHECK; + + assert(index >= 0); + assert(index < int(m_piece_map.size())); + + if (m_piece_map[index].downloading) + { + std::vector::const_iterator piece = std::find_if( + m_downloads.begin(), m_downloads.end() + , bind(&downloading_piece::index, _1) == index); + assert(piece != m_downloads.end()); + st = *piece; + st.info = 0; + return; + } + st.info = 0; + st.index = index; + st.writing = 0; + st.requested = 0; + if (m_piece_map[index].have()) + { + st.finished = blocks_in_piece(index); + return; + } + st.finished = 0; + } + void piece_picker::set_sequenced_download_threshold( int sequenced_download_threshold) { @@ -196,13 +225,8 @@ namespace libtorrent int block_index = num_downloads * m_blocks_per_piece; if (int(m_block_info.size()) < block_index + m_blocks_per_piece) { -#if defined _SECURE_SCL && _SECURE_SCL > 0 block_info* base = 0; - if (!m_block_info.empty()) - base = &m_block_info[0]; -#else - block_info* base = &m_block_info[0]; -#endif + if (!m_block_info.empty()) base = &m_block_info[0]; m_block_info.resize(block_index + m_blocks_per_piece); if (!m_downloads.empty() && &m_block_info[0] != base) { @@ -611,20 +635,15 @@ namespace libtorrent void piece_picker::sort_piece(std::vector::iterator dp) { assert(m_piece_map[dp->index].downloading); -#if defined _SECURE_SCL && _SECURE_SCL > 0 if (dp == m_downloads.begin()) return; -#endif int complete = dp->writing + dp->finished; for (std::vector::iterator i = dp, j(dp-1); - i != m_downloads.begin(); --i, --j) + i != m_downloads.begin() && j != m_downloads.begin(); --i, --j) { assert(j >= m_downloads.begin()); if (j->finished + j->writing >= complete) return; using std::swap; swap(*j, *i); -#if defined _SECURE_SCL && _SECURE_SCL > 0 - if (j == m_downloads.begin()) return; -#endif } } @@ -1063,8 +1082,12 @@ namespace libtorrent // downloaded to std::vector backup_blocks; + // When prefer_whole_pieces is set (usually set when downloading from + // fast peers) the partial pieces will not be prioritized, but actually + // ignored as long as possible. All blocks found in downloading + // pieces are regarded as backup blocks bool ignore_downloading_pieces = false; - if (!prefer_whole_pieces) + if (prefer_whole_pieces) { std::vector downloading_pieces; downloading_pieces.reserve(m_downloads.size()); @@ -1073,8 +1096,8 @@ namespace libtorrent { downloading_pieces.push_back(i->index); } - num_blocks = add_interesting_blocks(downloading_pieces, pieces - , interesting_blocks, backup_blocks, num_blocks + add_interesting_blocks(downloading_pieces, pieces + , backup_blocks, backup_blocks, num_blocks , prefer_whole_pieces, peer, speed, ignore_downloading_pieces); ignore_downloading_pieces = true; } @@ -1084,10 +1107,6 @@ namespace libtorrent // has filled the interesting_blocks with num_blocks // blocks. - // When prefer_whole_pieces is set (usually set when downloading from - // fast peers) the partial pieces will not be prioritized, but actually - // ignored as long as possible. - // +1 is to ignore pieces that no peer has. The bucket with index 0 contains // pieces that 0 other peers have. bucket will point to a bucket with // pieces with the same priority. It will be iterated in priority @@ -1140,8 +1159,7 @@ namespace libtorrent if (!backup_blocks.empty()) interesting_blocks.insert(interesting_blocks.end() - , backup_blocks.begin(), backup_blocks.begin() - + (std::min)(num_blocks, (int)backup_blocks.size())); + , backup_blocks.begin(), backup_blocks.end()); } void piece_picker::clear_peer(void* peer) @@ -1228,7 +1246,6 @@ namespace libtorrent // will be picked. if (prefer_whole_pieces && !exclusive) { - if (int(backup_blocks.size()) >= num_blocks) continue; for (int j = 0; j < num_blocks_in_piece; ++j) { block_info const& info = p->info[j]; @@ -1263,7 +1280,6 @@ namespace libtorrent && !exclusive_active && !ignore_speed_categories) { - if (int(backup_blocks.size()) >= num_blocks) continue; backup_blocks.push_back(piece_block(*i, j)); continue; } @@ -1276,9 +1292,9 @@ namespace libtorrent // to look for blocks until we have num_blocks // blocks that have not been requested from any // other peer. - interesting_blocks.push_back(piece_block(*i, j)); if (p->info[j].state == block_info::state_none) { + interesting_blocks.push_back(piece_block(*i, j)); // we have found a block that's free to download num_blocks--; // if we prefer whole pieces, continue picking from this @@ -1287,6 +1303,10 @@ namespace libtorrent assert(num_blocks >= 0); if (num_blocks == 0) return num_blocks; } + else + { + backup_blocks.push_back(piece_block(*i, j)); + } } assert(num_blocks >= 0 || prefer_whole_pieces); if (num_blocks < 0) num_blocks = 0; diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index 2f0d24b08..572f48d35 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -249,7 +249,7 @@ namespace libtorrent // with the other's, to see if we should abort another // peer_connection in favour of this one std::vector busy_pieces; - busy_pieces.reserve(10); + busy_pieces.reserve(num_requests); for (std::vector::iterator i = interesting_pieces.begin(); i != interesting_pieces.end(); ++i) @@ -272,6 +272,8 @@ namespace libtorrent // by somebody else. request it from this peer // and return c.add_request(*i); + assert(p.num_peers(*i) == 1); + assert(p.is_requested(*i)); num_requests--; } @@ -286,6 +288,8 @@ namespace libtorrent return; } + // if all blocks has the same number of peers on them + // we want to pick a random block std::random_shuffle(busy_pieces.begin(), busy_pieces.end()); // find the block with the fewest requests to it @@ -293,7 +297,11 @@ namespace libtorrent busy_pieces.begin(), busy_pieces.end() , bind(&piece_picker::num_peers, boost::cref(p), _1) < bind(&piece_picker::num_peers, boost::cref(p), _2)); - +#ifndef NDEBUG + piece_picker::downloading_piece st; + p.piece_info(i->piece_index, st); + assert(st.requested + st.finished + st.writing == p.blocks_in_piece(i->piece_index)); +#endif c.add_request(*i); c.send_block_requests(); } diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 793f95365..313ee6254 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -1125,6 +1125,7 @@ namespace libtorrent j.piece = r.piece; j.offset = r.start; j.buffer_size = r.length; + assert(r.length <= 16 * 1024); m_io_thread.add_job(j, handler); } diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp index 5a8acf512..6c6745f30 100755 --- a/libtorrent/src/web_peer_connection.cpp +++ b/libtorrent/src/web_peer_connection.cpp @@ -315,7 +315,14 @@ namespace libtorrent { INVARIANT_CHECK; - if (error) return; + if (error) + { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << "*** web_peer_connection error: " + << error.message() << "\n"; +#endif + return; + } boost::shared_ptr t = associated_torrent().lock(); assert(t);