libtorrent sync 1531

This commit is contained in:
Marcos Pinto 2007-09-04 04:01:19 +00:00
parent f1fde2dcf0
commit 0e3f5672a5
32 changed files with 567 additions and 330 deletions

View File

@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <queue>
#include <string>
#include <cassert>
#include <typeinfo>
#ifdef _MSC_VER
@ -56,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15

View File

@ -33,15 +33,17 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_ASSERT_HPP_INCLUDED
#define TORRENT_ASSERT_HPP_INCLUDED
#include <cassert>
#ifndef NDEBUG
#if defined __linux__ && defined _GNUC
#if defined __linux__ && defined __GNUC__
#ifdef assert
#undef assert
#endif
void assert_fail(int line, char const* file);
void assert_fail(const char* expr, int line, char const* file, char const* function);
#define assert(x) if (!(x)) assert_fail(__LINE__, __FILE__)
#define assert(x) if (!(x)) assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
#endif

View File

@ -240,7 +240,7 @@ namespace libtorrent
bool is_listening() const;
torrent_handle add_torrent(
torrent_info const& ti
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp>
#include "libtorrent/assert.hpp"
#if defined(__GNUC__) && __GNUC__ >= 4

View File

@ -64,10 +64,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <list>
#include <string>
#include <stdexcept>
#include <cassert>
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{

View File

@ -33,11 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED
#include <cassert>
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "zlib.h"
#ifdef TORRENT_USE_OPENSSL

View File

@ -34,14 +34,17 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_INTRUSIVE_PTR_BASE
#include <boost/detail/atomic_count.hpp>
#include <cassert>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
template<class T>
struct intrusive_ptr_base
{
intrusive_ptr_base(const intrusive_ptr_base<T>& b)
: m_refs(0) {}
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
{
assert(s->m_refs >= 0);

View File

@ -5,7 +5,7 @@
#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#include <cassert>
#include "libtorrent/assert.hpp"
namespace libtorrent
{

View File

@ -34,7 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
#define NODE_HPP
#include <algorithm>
#include <cassert>
#include <map>
#include <set>
@ -45,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/optional.hpp>

View File

@ -33,10 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
#define NODE_ID_HPP
#include <algorithm>
#include <cassert>
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent { namespace dht
{

View File

@ -35,13 +35,12 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <cassert>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/rc4.h>
#include "peer_id.hpp" // For sha1_hash
#include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp"
namespace libtorrent
{

View File

@ -152,11 +152,15 @@ namespace libtorrent
int upload_limit() const { return m_upload_limit; }
int download_limit() const { return m_download_limit; }
bool prefer_whole_pieces() const
{ return m_prefer_whole_pieces; }
int prefer_whole_pieces() const
{
if (m_prefer_whole_pieces == 0)
return peer_info_struct() && peer_info_struct()->on_parole ? 1 : 0;
return m_prefer_whole_pieces;
}
void prefer_whole_pieces(bool b)
{ m_prefer_whole_pieces = b; }
void prefer_whole_pieces(int num)
{ m_prefer_whole_pieces = num; }
bool request_large_blocks() const
{ return m_request_large_blocks; }
@ -219,6 +223,7 @@ namespace libtorrent
std::vector<bool> const& get_bitfield() const;
std::vector<int> const& allowed_fast();
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
void timed_out();
// this will cause this peer_connection to be disconnected.
@ -303,6 +308,7 @@ namespace libtorrent
void incoming_have_all();
void incoming_have_none();
void incoming_allowed_fast(int index);
void incoming_suggest(int index);
// the following functions appends messages
// to the send buffer
@ -493,6 +499,11 @@ namespace libtorrent
// the time we sent a request to
// this peer the last time
ptime m_last_request;
// the time we received the last
// piece request from the peer
ptime m_last_incoming_request;
// the time when we unchoked this peer
ptime m_last_unchoke;
int m_packet_size;
int m_recv_pos;
@ -590,7 +601,7 @@ namespace libtorrent
std::deque<peer_request> m_requests;
// the blocks we have reserved in the piece
// picker and will send to this peer.
// picker and will request from this peer.
std::deque<piece_block> m_request_queue;
// the queue of blocks we have requested
@ -658,12 +669,13 @@ namespace libtorrent
bool m_writing;
bool m_reading;
// if set to true, this peer will always prefer
// to request entire pieces, rather than blocks.
// if it is false, the download rate limit setting
// if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks.
// where n is the value of this variable.
// if it is 0, the download rate limit setting
// will be used to determine if whole pieces
// are preferred.
bool m_prefer_whole_pieces;
int m_prefer_whole_pieces;
// if this is true, the blocks picked by the piece
// picker will be merged before passed to the
@ -718,6 +730,10 @@ namespace libtorrent
// requested (regardless of choke state)
std::vector<int> m_allowed_fast;
// pieces that has been suggested to be
// downloaded from this peer
std::vector<int> m_suggested_pieces;
// the number of bytes send to the disk-io
// thread that hasn't yet been completely written.
int m_outstanding_writing_bytes;

View File

@ -35,12 +35,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <iomanip>
#include <cassert>
#include <cctype>
#include <algorithm>
#include <string>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{

View File

@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <vector>
#include <bitset>
#include <cassert>
#include <utility>
#ifdef _MSC_VER
@ -52,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
@ -191,9 +191,9 @@ namespace libtorrent
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
// The last argument is the policy::peer pointer for the peer that
// we'll download from.
void pick_pieces(const std::vector<bool>& pieces
void pick_pieces(std::vector<bool> const& pieces
, std::vector<piece_block>& interesting_blocks
, int num_pieces, bool prefer_whole_pieces
, int num_pieces, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool rarest_first) const;
@ -202,11 +202,11 @@ namespace libtorrent
// are added to interesting_blocks, and busy blocks are
// added to backup_blocks. num blocks is the number of
// blocks to be picked.
int add_interesting_blocks(const std::vector<int>& piece_list
int add_interesting_blocks(std::vector<int> const& piece_list
, const std::vector<bool>& pieces
, std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks
, int num_blocks, bool prefer_whole_pieces
, int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool ignore_downloading_pieces) const;
@ -284,6 +284,9 @@ namespace libtorrent
private:
std::pair<int, int> expand_piece(int piece, int whole_pieces
, std::vector<bool> const& have) const;
struct piece_pos
{
piece_pos() {}

View File

@ -142,6 +142,14 @@ namespace libtorrent
, entry const& resume_data = entry()
, bool compact_mode = true
, bool paused = false
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;
torrent_handle add_torrent(
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data = entry()
, bool compact_mode = true
, bool paused = false
, storage_constructor_type sc = default_storage_constructor);
torrent_handle add_torrent(

View File

@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/limits.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
@ -147,10 +148,11 @@ namespace libtorrent
};
typedef storage_interface* (&storage_constructor_type)(
torrent_info const&, fs::path const&
boost::intrusive_ptr<torrent_info const>, fs::path const&
, file_pool&);
TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti
TORRENT_EXPORT storage_interface* default_storage_constructor(
boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path, file_pool& fp);
// returns true if the filesystem the path relies on supports
@ -169,7 +171,7 @@ namespace libtorrent
piece_manager(
boost::shared_ptr<void> const& torrent
, torrent_info const& ti
, boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path
, file_pool& fp
, disk_io_thread& io
@ -227,7 +229,7 @@ namespace libtorrent
{ return m_compact_mode; }
#ifndef NDEBUG
std::string name() const { return m_info.name(); }
std::string name() const { return m_info->name(); }
#endif
private:
@ -283,7 +285,7 @@ namespace libtorrent
// a bitmask representing the pieces we have
std::vector<bool> m_have_piece;
torrent_info const& m_info;
boost::intrusive_ptr<torrent_info const> m_info;
// slots that haven't had any file storage allocated
std::vector<int> m_unallocated_slots;
@ -313,12 +315,6 @@ namespace libtorrent
mutable boost::recursive_mutex m_mutex;
bool m_allocating;
boost::mutex m_allocating_monitor;
boost::condition m_allocating_condition;
// these states are used while checking/allocating the torrent
enum {
// the default initial state
state_none,
@ -333,6 +329,11 @@ namespace libtorrent
} m_state;
int m_current_slot;
// this is saved in case we need to instantiate a new
// storage (osed when remapping files)
storage_constructor_type m_storage_constructor;
// temporary buffer used while checking
std::vector<char> m_piece_data;
// this maps a piece hash to piece index. It will be
@ -340,6 +341,8 @@ namespace libtorrent
// isn't needed)
std::multimap<sha1_hash, int> m_hash_to_piece;
// this map contains partial hashes for downloading
// pieces.
std::map<int, partial_hash> m_piece_hasher;
disk_io_thread& m_io_thread;

View File

@ -97,7 +97,7 @@ namespace libtorrent
torrent(
aux::session_impl& ses
, aux::checker_impl& checker
, torrent_info const& tf
, boost::intrusive_ptr<torrent_info> tf
, fs::path const& save_path
, tcp::endpoint const& net_interface
, bool compact_mode
@ -469,14 +469,14 @@ namespace libtorrent
bool is_seed() const
{
return valid_metadata()
&& m_num_pieces == m_torrent_file.num_pieces();
&& m_num_pieces == m_torrent_file->num_pieces();
}
// this is true if we have all the pieces that we want
bool is_finished() const
{
if (is_seed()) return true;
return valid_metadata() && m_torrent_file.num_pieces()
return valid_metadata() && m_torrent_file->num_pieces()
- m_num_pieces - m_picker->num_filtered() == 0;
}
@ -498,7 +498,7 @@ namespace libtorrent
}
piece_manager& filesystem();
torrent_info const& torrent_file() const
{ return m_torrent_file; }
{ return *m_torrent_file; }
std::vector<announce_entry> const& trackers() const
{ return m_trackers; }
@ -539,7 +539,7 @@ namespace libtorrent
bool ready_for_connections() const
{ return m_connections_initialized; }
bool valid_metadata() const
{ return m_torrent_file.is_valid(); }
{ return m_torrent_file->is_valid(); }
// parses the info section from the given
// bencoded tree and moves the torrent
@ -563,7 +563,7 @@ namespace libtorrent
void update_peer_interest();
torrent_info m_torrent_file;
boost::intrusive_ptr<torrent_info> m_torrent_file;
// is set to true when the torrent has
// been aborted.

View File

@ -57,6 +57,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_request.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
namespace libtorrent
{
@ -96,7 +97,7 @@ namespace libtorrent
virtual const char* what() const throw() { return "invalid torrent file"; }
};
class TORRENT_EXPORT torrent_info
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
{
public:

View File

@ -32,9 +32,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef NDEBUG
#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
void assert_fail(int line, char const* file)
void assert_fail(char const* expr, int line, char const* file, char const* function)
{
fprintf(stderr, "assertion failed. Please file a bugreport at "
@ -42,9 +44,11 @@ void assert_fail(int line, char const* file)
"Please include the following information:\n\n"
"file: '%s'\n"
"line: %d\n"
"stack:\n", file, line);
"function: %s\n"
"expression: %s\n"
"stack:\n", file, line, function, expr);
void* stacktrace[50];
void* stack[50];
int size = backtrace(stack, 50);
char** symbols = backtrace_symbols(stack, size);
@ -54,6 +58,7 @@ void assert_fail(int line, char const* file)
}
free(symbols);
exit(1);
}
#endif

View File

@ -1062,8 +1062,14 @@ namespace libtorrent
if (!m_supports_fast)
throw protocol_error("got 'suggest_piece' without FAST extension support");
// just ignore for now
return;
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
const char* ptr = recv_buffer.begin + 1;
int piece = detail::read_uint32(ptr);
incoming_suggest(piece);
}
void bt_peer_connection::on_have_all(int received)

View File

@ -31,9 +31,9 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/pch.hpp"
#include "libtorrent/assert.hpp"
#include <string>
#include <cassert>
#include <stdexcept>
#include <sstream>
#include <iomanip>

View File

@ -34,10 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <iomanip>
#include <cassert>
#include <boost/bind.hpp>
#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/assert.hpp"
using boost::bind;

View File

@ -32,13 +32,13 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_DISABLE_ENCRYPTION
#include <cassert>
#include <algorithm>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include "libtorrent/pe_crypto.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent {

View File

@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/policy.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/assert.hpp"
using boost::bind;
using boost::shared_ptr;
@ -76,6 +77,8 @@ namespace libtorrent
, m_timeout(m_ses.settings().peer_timeout)
, m_last_piece(time_now())
, m_last_request(time_now())
, m_last_incoming_request(min_time())
, m_last_unchoke(min_time())
, m_packet_size(0)
, m_recv_pos(0)
, m_current_send_buffer(0)
@ -154,6 +157,8 @@ namespace libtorrent
, m_timeout(m_ses.settings().peer_timeout)
, m_last_piece(time_now())
, m_last_request(time_now())
, m_last_incoming_request(min_time())
, m_last_unchoke(min_time())
, m_packet_size(0)
, m_recv_pos(0)
, m_current_send_buffer(0)
@ -338,7 +343,7 @@ namespace libtorrent
// if this is a web seed. we don't have a peer_info struct
if (m_peer_info) m_peer_info->seed = true;
// if we're a seed too, disconnect
if (t->is_seed())
if (t->is_finished())
{
throw std::runtime_error("seed to seed connection redundant, disconnecting");
}
@ -395,7 +400,12 @@ namespace libtorrent
{
// dont announce during handshake
if (in_handshake()) return;
// remove suggested pieces that we have
std::vector<int>::iterator i = std::find(
m_suggested_pieces.begin(), m_suggested_pieces.end(), index);
if (i != m_suggested_pieces.end()) m_suggested_pieces.erase(i);
// optimization, don't send have messages
// to peers that already have the piece
if (!m_ses.settings().send_redundant_have
@ -511,6 +521,7 @@ namespace libtorrent
assert(t);
assert(t->valid_metadata());
torrent_info const& ti = t->torrent_file();
return p.piece >= 0
&& p.piece < t->torrent_file().num_pieces()
@ -518,11 +529,13 @@ namespace libtorrent
&& p.start >= 0
&& (p.length == t->block_size()
|| (p.length < t->block_size()
&& p.piece == t->torrent_file().num_pieces()-1
&& p.start + p.length == t->torrent_file().piece_size(p.piece))
&& p.piece == ti.num_pieces()-1
&& p.start + p.length == ti.piece_size(p.piece))
|| (m_request_large_blocks
&& p.length <= t->torrent_file().piece_size(p.piece)))
&& p.start + p.length <= t->torrent_file().piece_size(p.piece)
&& p.length <= ti.piece_length() * m_prefer_whole_pieces == 0 ?
1 : m_prefer_whole_pieces))
&& p.piece * size_type(ti.piece_length()) + p.start + p.length
<= ti.total_size()
&& (p.start % t->block_size() == 0);
}
@ -723,6 +736,33 @@ namespace libtorrent
}
}
// -----------------------------
// -------- REJECT PIECE -------
// -----------------------------
void peer_connection::incoming_suggest(int index)
{
INVARIANT_CHECK;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " <== SUGGEST_PIECE [ piece: " << index << " ]\n";
#endif
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t) return;
if (t->have_piece(index)) return;
if (m_suggested_pieces.size() > 9)
m_suggested_pieces.erase(m_suggested_pieces.begin());
m_suggested_pieces.push_back(index);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " ** SUGGEST_PIECE [ piece: " << index << " added to set: " << m_suggested_pieces.size() << " ]\n";
#endif
}
// -----------------------------
// ---------- UNCHOKE ----------
// -----------------------------
@ -877,7 +917,7 @@ namespace libtorrent
{
assert(m_peer_info);
m_peer_info->seed = true;
if (t->is_seed())
if (t->is_finished())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
}
@ -948,7 +988,7 @@ namespace libtorrent
// if this is a web seed. we don't have a peer_info struct
if (m_peer_info) m_peer_info->seed = true;
// if we're a seed too, disconnect
if (t->is_seed())
if (t->is_finished())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
}
@ -1096,6 +1136,7 @@ namespace libtorrent
else
{
m_requests.push_back(r);
m_last_incoming_request = time_now();
fill_send_buffer();
}
}
@ -1476,7 +1517,7 @@ namespace libtorrent
#endif
// if we're a seed too, disconnect
if (t->is_seed())
if (t->is_finished())
throw protocol_error("seed to seed connection redundant, disconnecting");
assert(!m_have_piece.empty());
@ -1585,6 +1626,7 @@ namespace libtorrent
assert(block.block_index >= 0);
assert(block.block_index < t->torrent_file().piece_size(block.piece_index));
assert(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0));
assert(!t->have_piece(block.piece_index));
piece_picker::piece_state_t state;
peer_speed_t speed = peer_speed();
@ -1701,6 +1743,7 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_choked) return;
m_last_unchoke = time_now();
write_unchoke();
m_choked = false;
@ -1776,21 +1819,27 @@ namespace libtorrent
// blocks that are in the same piece into larger requests
if (m_request_large_blocks)
{
while (!m_request_queue.empty()
&& m_request_queue.front().piece_index == r.piece
&& m_request_queue.front().block_index == block.block_index + 1)
int blocks_per_piece = t->torrent_file().piece_length() / t->block_size();
while (!m_request_queue.empty())
{
// check to see if this block is connected to the previous one
// if it is, merge them, otherwise, break this merge loop
piece_block const& front = m_request_queue.front();
if (front.piece_index * blocks_per_piece + front.block_index
!= block.piece_index * blocks_per_piece + block.block_index + 1)
break;
block = m_request_queue.front();
m_request_queue.pop_front();
m_download_queue.push_back(block);
/*
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " *** REQUEST-QUEUE** [ "
<< " *** MERGING REQUEST ** [ "
"piece: " << block.piece_index << " | "
"block: " << block.block_index << " ]\n";
#endif
*/
block_offset = block.block_index * t->block_size();
block_size = (std::min)((int)t->torrent_file().piece_size(
block.piece_index) - block_offset, t->block_size());
@ -2137,7 +2186,7 @@ namespace libtorrent
// maintain the share ratio given by m_ratio
// with all peers.
if (t->is_seed() || is_choked() || t->ratio() == 0.0f)
if (t->is_finished() || is_choked() || t->ratio() == 0.0f)
{
// if we have downloaded more than one piece more
// than we have uploaded OR if we are a seed
@ -2862,9 +2911,20 @@ namespace libtorrent
// if the peer hasn't said a thing for a certain
// time, it is considered to have timed out
time_duration d;
d = time_now() - m_last_receive;
d = now - m_last_receive;
if (d > seconds(m_timeout)) return true;
// disconnect peers that we unchoked, but
// they didn't send a request within 20 seconds.
// but only if we're a seed
boost::shared_ptr<torrent> t = m_torrent.lock();
d = now - (std::max)(m_last_unchoke, m_last_incoming_request);
if (m_requests.empty()
&& !m_choked
&& m_peer_interested
&& t && t->is_finished()
&& d > seconds(20)) return true;
// TODO: as long as we have less than 95% of the
// global (or local) connection limit, connections should
// never time out for another reason

View File

@ -201,7 +201,7 @@ namespace libtorrent
, end(in.end()); i != end; ++i)
{
m_piece_map[*i].index = c++;
assert(m_piece_map[*i].priority(old_limit) == old_limit);
assert(m_piece_map[*i].priority(old_limit) == old_limit * 2);
}
}
}
@ -1079,7 +1079,7 @@ namespace libtorrent
// or slow once they're started.
void piece_picker::pick_pieces(const std::vector<bool>& pieces
, std::vector<piece_block>& interesting_blocks
, int num_blocks, bool prefer_whole_pieces
, int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed, bool rarest_first) const
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
@ -1102,7 +1102,7 @@ namespace libtorrent
// 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 > 0 || !rarest_first)
{
std::vector<int> downloading_pieces;
downloading_pieces.reserve(m_downloads.size());
@ -1111,34 +1111,46 @@ namespace libtorrent
{
downloading_pieces.push_back(i->index);
}
add_interesting_blocks(downloading_pieces, pieces
, backup_blocks, backup_blocks, num_blocks
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
if (prefer_whole_pieces > 0)
{
add_interesting_blocks(downloading_pieces, pieces
, backup_blocks, backup_blocks, num_blocks
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
}
else
{
num_blocks = add_interesting_blocks(downloading_pieces, pieces
, interesting_blocks, backup_blocks, num_blocks
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
}
ignore_downloading_pieces = true;
}
// this loop will loop from pieces with priority 1 and up
// until we either reach the end of the piece list or
// has filled the interesting_blocks with num_blocks
// blocks.
// +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
// order (high priority/rare pices first). The content of each
// bucket is randomized
for (std::vector<std::vector<int> >::const_iterator bucket
= m_piece_info.begin() + 1; bucket != m_piece_info.end();
++bucket)
if (rarest_first)
{
if (bucket->empty()) continue;
num_blocks = add_interesting_blocks(*bucket, pieces
, interesting_blocks, backup_blocks, num_blocks
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
assert(num_blocks >= 0);
if (num_blocks == 0) return;
if (rarest_first) continue;
// this loop will loop from pieces with priority 1 and up
// until we either reach the end of the piece list or
// has filled the interesting_blocks with num_blocks
// blocks.
// +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
// order (high priority/rare pices first). The content of each
// bucket is randomized
for (std::vector<std::vector<int> >::const_iterator bucket
= m_piece_info.begin() + 1; num_blocks > 0 && bucket != m_piece_info.end();
++bucket)
{
if (bucket->empty()) continue;
num_blocks = add_interesting_blocks(*bucket, pieces
, interesting_blocks, backup_blocks, num_blocks
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
assert(num_blocks >= 0);
}
}
else
{
// we're not using rarest first (only for the first
// bucket, since that's where the currently downloading
// pieces are)
@ -1147,8 +1159,9 @@ namespace libtorrent
while (num_blocks > 0)
{
while (!pieces[piece]
|| m_piece_map[piece].index == piece_pos::we_have_index
|| m_piece_map[piece].priority(m_sequenced_download_threshold) < 2)
|| m_piece_map[piece].have()
|| m_piece_map[piece].downloading
|| m_piece_map[piece].filtered())
{
++piece;
if (piece == int(m_piece_map.size())) piece = 0;
@ -1158,23 +1171,28 @@ namespace libtorrent
assert(m_piece_map[piece].downloading == false);
int num_blocks_in_piece = blocks_in_piece(piece);
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
num_blocks_in_piece = num_blocks;
for (int j = 0; j < num_blocks_in_piece; ++j)
interesting_blocks.push_back(piece_block(piece, j));
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
++piece;
int start, end;
boost::tie(start, end) = expand_piece(piece, prefer_whole_pieces, pieces);
for (int k = start; k < end; ++k)
{
int num_blocks_in_piece = blocks_in_piece(k);
if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks)
num_blocks_in_piece = num_blocks;
for (int j = 0; j < num_blocks_in_piece; ++j)
{
interesting_blocks.push_back(piece_block(k, j));
--num_blocks;
}
}
piece = end;
if (piece == int(m_piece_map.size())) piece = 0;
// could not find any more pieces
if (piece == start_piece) return;
}
if (num_blocks == 0) return;
break;
}
assert(num_blocks > 0);
if (num_blocks <= 0) return;
if (!backup_blocks.empty())
interesting_blocks.insert(interesting_blocks.end()
@ -1222,7 +1240,7 @@ namespace libtorrent
, std::vector<bool> const& pieces
, std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks
, int num_blocks, bool prefer_whole_pieces
, int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool ignore_downloading_pieces) const
{
@ -1266,7 +1284,7 @@ namespace libtorrent
// blocks to the backup list. If the prioritized
// blocks aren't enough, blocks from this list
// will be picked.
if (prefer_whole_pieces && !exclusive)
if (prefer_whole_pieces > 0 && !exclusive)
{
for (int j = 0; j < num_blocks_in_piece; ++j)
{
@ -1321,7 +1339,7 @@ namespace libtorrent
num_blocks--;
// if we prefer whole pieces, continue picking from this
// piece even though we have num_blocks
if (prefer_whole_pieces) continue;
if (prefer_whole_pieces > 0) continue;
assert(num_blocks >= 0);
if (num_blocks == 0) return num_blocks;
}
@ -1330,23 +1348,68 @@ namespace libtorrent
backup_blocks.push_back(piece_block(*i, j));
}
}
assert(num_blocks >= 0 || prefer_whole_pieces);
assert(num_blocks >= 0 || prefer_whole_pieces > 0);
if (num_blocks < 0) num_blocks = 0;
}
else
{
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
num_blocks_in_piece = num_blocks;
for (int j = 0; j < num_blocks_in_piece; ++j)
interesting_blocks.push_back(piece_block(*i, j));
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
// pick a new piece
if (prefer_whole_pieces == 0)
{
if (num_blocks_in_piece > num_blocks)
num_blocks_in_piece = num_blocks;
for (int j = 0; j < num_blocks_in_piece; ++j)
interesting_blocks.push_back(piece_block(*i, j));
num_blocks -= num_blocks_in_piece;
}
else
{
int start, end;
boost::tie(start, end) = expand_piece(*i, prefer_whole_pieces, pieces);
for (int k = start; k < end; ++k)
{
num_blocks_in_piece = blocks_in_piece(k);
for (int j = 0; j < num_blocks_in_piece; ++j)
{
interesting_blocks.push_back(piece_block(k, j));
--num_blocks;
}
}
}
}
assert(num_blocks >= 0);
if (num_blocks == 0) return num_blocks;
if (num_blocks <= 0) return num_blocks < 0 ? 0 : num_blocks;
}
return num_blocks;
}
std::pair<int, int> piece_picker::expand_piece(int piece, int whole_pieces
, std::vector<bool> const& have) const
{
if (whole_pieces == 0) return std::make_pair(piece, piece + 1);
int start = piece - 1;
int lower_limit = piece - whole_pieces;
if (lower_limit < -1) lower_limit = -1;
while (start > lower_limit
&& have[start]
&& !m_piece_map[start].downloading
&& !m_piece_map[start].filtered()
&& !m_piece_map[start].have())
--start;
++start;
assert(start >= 0);
int end = piece + 1;
int upper_limit = start + whole_pieces;
if (upper_limit > int(m_piece_map.size())) upper_limit = int(m_piece_map.size());
while (end < upper_limit
&& have[end]
&& !m_piece_map[end].downloading
&& !m_piece_map[end].filtered()
&& !m_piece_map[end].have())
++end;
return std::make_pair(start, end);
}
bool piece_picker::is_piece_finished(int index) const
{
assert(index < (int)m_piece_map.size());
@ -1432,6 +1495,7 @@ namespace libtorrent
assert(block.block_index >= 0);
assert(block.piece_index < (int)m_piece_map.size());
assert(block.block_index < blocks_in_piece(block.piece_index));
assert(!m_piece_map[block.piece_index].have());
piece_pos& p = m_piece_map[block.piece_index];
if (p.downloading == 0)

View File

@ -209,16 +209,15 @@ namespace libtorrent
std::vector<piece_block> interesting_pieces;
interesting_pieces.reserve(100);
bool prefer_whole_pieces = c.prefer_whole_pieces()
|| (c.peer_info_struct() && c.peer_info_struct()->on_parole);
int prefer_whole_pieces = c.prefer_whole_pieces();
bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold;
if (!prefer_whole_pieces)
if (prefer_whole_pieces == 0)
{
prefer_whole_pieces = c.statistics().download_payload_rate()
* t.settings().whole_pieces_threshold
> t.torrent_file().piece_length();
> t.torrent_file().piece_length() ? 1 : 0;
}
// if we prefer whole pieces, the piece picker will pick at least
@ -258,6 +257,18 @@ namespace libtorrent
}
else
{
if (!c.suggested_pieces().empty())
{
// if the peer has suggested us to download certain pieces
// try to pick among those primarily
std::vector<int> const& suggested = c.suggested_pieces();
p.add_interesting_blocks(suggested, c.get_bitfield()
, interesting_pieces, busy_pieces, num_requests
, prefer_whole_pieces, c.peer_info_struct(), state
, false);
}
// picks the interesting pieces from this peer
// the integer is the number of pieces that
// should be guaranteed to be available for download
@ -266,15 +277,18 @@ namespace libtorrent
// the last argument is if we should prefer whole pieces
// for this peer. If we're downloading one piece in 20 seconds
// then use this mode.
p.pick_pieces(c.get_bitfield(), interesting_pieces
, num_requests, prefer_whole_pieces, c.peer_info_struct()
, state, rarest_first);
busy_pieces.reserve(10);
if (int(interesting_pieces.size()) < num_requests)
p.pick_pieces(c.get_bitfield(), interesting_pieces
, num_requests, prefer_whole_pieces, c.peer_info_struct()
, state, rarest_first);
}
#ifdef TORRENT_VERBOSE_LOGGING
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ picked: " << interesting_pieces.size() << " ]\n";
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ php: " << prefer_whole_pieces
<< " picked: " << interesting_pieces.size() << " ]\n";
#endif
std::deque<piece_block> const& dq = c.download_queue();
std::deque<piece_block> const& rq = c.request_queue();
for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
i != interesting_pieces.end(); ++i)
{
@ -282,8 +296,6 @@ namespace libtorrent
{
if (num_requests <= 0) break;
// don't request pieces we already have in our request queue
const std::deque<piece_block>& dq = c.download_queue();
const std::deque<piece_block>& rq = c.request_queue();
if (std::find(dq.begin(), dq.end(), *i) != dq.end()
|| std::find(rq.begin(), rq.end(), *i) != rq.end())
continue;
@ -516,6 +528,7 @@ namespace libtorrent
int max_failcount = m_torrent->settings().max_failcount;
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
bool finished = m_torrent->is_finished();
aux::session_impl& ses = m_torrent->session();
@ -524,7 +537,7 @@ namespace libtorrent
if (i->connection) continue;
if (i->banned) continue;
if (i->type == peer::not_connectable) continue;
if (i->seed && m_torrent->is_seed()) continue;
if (i->seed && finished) continue;
if (i->failcount >= max_failcount) continue;
if (now - i->connected < seconds(i->failcount * min_reconnect_time))
continue;
@ -1179,7 +1192,7 @@ namespace libtorrent
&& m_torrent->session().num_uploads() < m_torrent->session().max_uploads()
&& (m_torrent->ratio() == 0
|| c.share_diff() >= -free_upload_amount
|| m_torrent->is_seed()))
|| m_torrent->is_finished()))
{
m_torrent->session().unchoke_peer(c);
}

View File

@ -181,6 +181,19 @@ namespace libtorrent
, bool compact_mode
, bool paused
, storage_constructor_type sc)
{
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
return m_impl->add_torrent(tip, save_path, resume_data
, compact_mode, sc, paused);
}
torrent_handle session::add_torrent(
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
, bool paused
, storage_constructor_type sc)
{
return m_impl->add_torrent(ti, save_path, resume_data
, compact_mode, sc, paused);

View File

@ -786,8 +786,30 @@ namespace detail
return;
}
// check if we have any active torrents
// if we don't reject the connection
if (m_torrents.empty())
{
return;
}
else
{
bool has_active_torrent = false;
for (torrent_map::iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i)
{
if (!i->second->is_paused())
{
has_active_torrent = true;
break;
}
}
if (!has_active_torrent)
return;
}
boost::intrusive_ptr<peer_connection> c(
new bt_peer_connection(*this, s, 0));
new bt_peer_connection(*this, s, 0));
#ifndef NDEBUG
c->m_in_constructor = false;
#endif
@ -1454,7 +1476,7 @@ namespace detail
}
torrent_handle session_impl::add_torrent(
torrent_info const& ti
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
@ -1466,7 +1488,7 @@ namespace detail
assert(m_external_listen_port > 0);
assert(!save_path.empty());
if (ti.begin_files() == ti.end_files())
if (ti->begin_files() == ti->end_files())
throw std::runtime_error("no files in torrent");
// lock the session and the checker thread (the order is important!)
@ -1479,11 +1501,11 @@ namespace detail
throw std::runtime_error("session is closing");
// is the torrent already active?
if (!find_torrent(ti.info_hash()).expired())
if (!find_torrent(ti->info_hash()).expired())
throw duplicate_torrent();
// is the torrent currently being checked?
if (m_checker_impl.find_torrent(ti.info_hash()))
if (m_checker_impl.find_torrent(ti->info_hash()))
throw duplicate_torrent();
// create the torrent and the data associated with
@ -1508,13 +1530,13 @@ namespace detail
new aux::piece_checker_data);
d->torrent_ptr = torrent_ptr;
d->save_path = save_path;
d->info_hash = ti.info_hash();
d->info_hash = ti->info_hash();
d->resume_data = resume_data;
#ifndef TORRENT_DISABLE_DHT
if (m_dht)
{
torrent_info::nodes_t const& nodes = ti.nodes();
torrent_info::nodes_t const& nodes = ti->nodes();
std::for_each(nodes.begin(), nodes.end(), bind(
(void(dht::dht_tracker::*)(std::pair<std::string, int> const&))
&dht::dht_tracker::add_node
@ -1528,7 +1550,7 @@ namespace detail
// job in its queue
m_checker_impl.m_cond.notify_one();
return torrent_handle(this, &m_checker_impl, ti.info_hash());
return torrent_handle(this, &m_checker_impl, ti->info_hash());
}
torrent_handle session_impl::add_torrent(

View File

@ -345,11 +345,11 @@ namespace libtorrent
class storage : public storage_interface, boost::noncopyable
{
public:
storage(torrent_info const& info, fs::path const& path, file_pool& fp)
storage(boost::intrusive_ptr<torrent_info const> info, fs::path const& path, file_pool& fp)
: m_info(info)
, m_files(fp)
{
assert(info.begin_files(true) != info.end_files(true));
assert(info->begin_files(true) != info->end_files(true));
m_save_path = fs::complete(path);
assert(m_save_path.is_complete());
}
@ -369,11 +369,9 @@ namespace libtorrent
size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero);
~storage()
{
m_files.release(this);
}
{ m_files.release(this); }
torrent_info const& m_info;
boost::intrusive_ptr<torrent_info const> m_info;
fs::path m_save_path;
// the file pool is typically stored in
// the session, to make all storage
@ -412,8 +410,8 @@ namespace libtorrent
{
// first, create all missing directories
fs::path last_path;
for (torrent_info::file_iterator file_iter = m_info.begin_files(true),
end_iter = m_info.end_files(true); file_iter != end_iter; ++file_iter)
for (torrent_info::file_iterator file_iter = m_info->begin_files(true),
end_iter = m_info->end_files(true); file_iter != end_iter; ++file_iter)
{
fs::path dir = (m_save_path / file_iter->path).branch_path();
@ -461,7 +459,7 @@ namespace libtorrent
void storage::write_resume_data(entry& rd) const
{
std::vector<std::pair<size_type, std::time_t> > file_sizes
= get_filesizes(m_info, m_save_path);
= get_filesizes(*m_info, m_save_path);
rd["file sizes"] = entry::list_type();
entry::list_type& fl = rd["file sizes"].list();
@ -495,7 +493,7 @@ namespace libtorrent
}
entry::list_type& slots = rd["slots"].list();
bool seed = int(slots.size()) == m_info.num_pieces()
bool seed = int(slots.size()) == m_info->num_pieces()
&& std::find_if(slots.begin(), slots.end()
, boost::bind<bool>(std::less<int>()
, boost::bind((size_type const& (entry::*)() const)
@ -510,11 +508,11 @@ namespace libtorrent
if (seed)
{
if (m_info.num_files(true) != (int)file_sizes.size())
if (m_info->num_files(true) != (int)file_sizes.size())
{
error = "the number of files does not match the torrent (num: "
+ boost::lexical_cast<std::string>(file_sizes.size()) + " actual: "
+ boost::lexical_cast<std::string>(m_info.num_files(true)) + ")";
+ boost::lexical_cast<std::string>(m_info->num_files(true)) + ")";
return false;
}
@ -522,8 +520,8 @@ namespace libtorrent
fs = file_sizes.begin();
// the resume data says we have the entire torrent
// make sure the file sizes are the right ones
for (torrent_info::file_iterator i = m_info.begin_files(true)
, end(m_info.end_files(true)); i != end; ++i, ++fs)
for (torrent_info::file_iterator i = m_info->begin_files(true)
, end(m_info->end_files(true)); i != end; ++i, ++fs)
{
if (i->size != fs->first)
{
@ -536,7 +534,7 @@ namespace libtorrent
return true;
}
return match_filesizes(m_info, m_save_path, file_sizes
return match_filesizes(*m_info, m_save_path, file_sizes
, !full_allocation_mode, &error);
}
@ -575,11 +573,11 @@ namespace libtorrent
m_files.release(this);
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400
old_path = safe_convert((m_save_path / m_info.name()).string());
new_path = safe_convert((save_path / m_info.name()).string());
old_path = safe_convert((m_save_path / m_info->name()).string());
new_path = safe_convert((save_path / m_info->name()).string());
#else
old_path = m_save_path / m_info.name();
new_path = save_path / m_info.name();
old_path = m_save_path / m_info->name();
new_path = save_path / m_info->name();
#endif
try
@ -601,7 +599,7 @@ namespace libtorrent
/*
void storage::shuffle()
{
int num_pieces = m_info.num_pieces();
int num_pieces = m_info->num_pieces();
std::vector<int> pieces(num_pieces);
for (std::vector<int>::iterator i = pieces.begin();
@ -618,7 +616,7 @@ namespace libtorrent
{
const int slot_index = targets[i];
const int piece_index = pieces[i];
const int slot_size =static_cast<int>(m_info.piece_size(slot_index));
const int slot_size =static_cast<int>(m_info->piece_size(slot_index));
std::vector<char> buf(slot_size);
read(&buf[0], piece_index, 0, slot_size);
write(&buf[0], slot_index, 0, slot_size);
@ -629,7 +627,7 @@ namespace libtorrent
void storage::move_slot(int src_slot, int dst_slot)
{
int piece_size = m_info.piece_size(dst_slot);
int piece_size = m_info->piece_size(dst_slot);
m_scratch_buffer.resize(piece_size);
read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true);
write(&m_scratch_buffer[0], dst_slot, 0, piece_size);
@ -638,9 +636,9 @@ namespace libtorrent
void storage::swap_slots(int slot1, int slot2)
{
// the size of the target slot is the size of the piece
int piece_size = m_info.piece_length();
int piece1_size = m_info.piece_size(slot2);
int piece2_size = m_info.piece_size(slot1);
int piece_size = m_info->piece_length();
int piece1_size = m_info->piece_size(slot2);
int piece2_size = m_info->piece_size(slot1);
m_scratch_buffer.resize(piece_size * 2);
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
@ -651,10 +649,10 @@ namespace libtorrent
void storage::swap_slots3(int slot1, int slot2, int slot3)
{
// the size of the target slot is the size of the piece
int piece_size = m_info.piece_length();
int piece1_size = m_info.piece_size(slot2);
int piece2_size = m_info.piece_size(slot3);
int piece3_size = m_info.piece_size(slot1);
int piece_size = m_info->piece_length();
int piece1_size = m_info->piece_size(slot2);
int piece2_size = m_info->piece_size(slot3);
int piece3_size = m_info->piece_size(slot1);
m_scratch_buffer.resize(piece_size * 2);
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
@ -681,25 +679,25 @@ namespace libtorrent
, bool fill_zero)
{
assert(buf != 0);
assert(slot >= 0 && slot < m_info.num_pieces());
assert(slot >= 0 && slot < m_info->num_pieces());
assert(offset >= 0);
assert(offset < m_info.piece_size(slot));
assert(offset < m_info->piece_size(slot));
assert(size > 0);
#ifndef NDEBUG
std::vector<file_slice> slices
= m_info.map_block(slot, offset, size, true);
= m_info->map_block(slot, offset, size, true);
assert(!slices.empty());
#endif
size_type start = slot * (size_type)m_info.piece_length() + offset;
assert(start + size <= m_info.total_size());
size_type start = slot * (size_type)m_info->piece_length() + offset;
assert(start + size <= m_info->total_size());
// find the file iterator and file offset
size_type file_offset = start;
std::vector<file_entry>::const_iterator file_iter;
for (file_iter = m_info.begin_files(true);;)
for (file_iter = m_info->begin_files(true);;)
{
if (file_offset < file_iter->size)
break;
@ -732,7 +730,7 @@ namespace libtorrent
#endif
int left_to_read = size;
int slot_size = static_cast<int>(m_info.piece_size(slot));
int slot_size = static_cast<int>(m_info->piece_size(slot));
if (offset + left_to_read > slot_size)
left_to_read = slot_size - offset;
@ -757,7 +755,7 @@ namespace libtorrent
assert(int(slices.size()) > counter);
size_type slice_size = slices[counter].size;
assert(slice_size == read_bytes);
assert(m_info.file_at(slices[counter].file_index, true).path
assert(m_info->file_at(slices[counter].file_index, true).path
== file_iter->path);
#endif
@ -807,30 +805,30 @@ namespace libtorrent
{
assert(buf != 0);
assert(slot >= 0);
assert(slot < m_info.num_pieces());
assert(slot < m_info->num_pieces());
assert(offset >= 0);
assert(size > 0);
#ifndef NDEBUG
std::vector<file_slice> slices
= m_info.map_block(slot, offset, size, true);
= m_info->map_block(slot, offset, size, true);
assert(!slices.empty());
#endif
size_type start = slot * (size_type)m_info.piece_length() + offset;
size_type start = slot * (size_type)m_info->piece_length() + offset;
// find the file iterator and file offset
size_type file_offset = start;
std::vector<file_entry>::const_iterator file_iter;
for (file_iter = m_info.begin_files(true);;)
for (file_iter = m_info->begin_files(true);;)
{
if (file_offset < file_iter->size)
break;
file_offset -= file_iter->size;
++file_iter;
assert(file_iter != m_info.end_files(true));
assert(file_iter != m_info->end_files(true));
}
fs::path p(m_save_path / file_iter->path);
@ -850,7 +848,7 @@ namespace libtorrent
}
int left_to_write = size;
int slot_size = static_cast<int>(m_info.piece_size(slot));
int slot_size = static_cast<int>(m_info->piece_size(slot));
if (offset + left_to_write > slot_size)
left_to_write = slot_size - offset;
@ -874,7 +872,7 @@ namespace libtorrent
{
assert(int(slices.size()) > counter);
assert(slices[counter].size == write_bytes);
assert(m_info.file_at(slices[counter].file_index, true).path
assert(m_info->file_at(slices[counter].file_index, true).path
== file_iter->path);
assert(buf_pos >= 0);
@ -902,7 +900,7 @@ namespace libtorrent
#endif
++file_iter;
assert(file_iter != m_info.end_files(true));
assert(file_iter != m_info->end_files(true));
fs::path p = m_save_path / file_iter->path;
file_offset = 0;
out = m_files.open_file(
@ -913,7 +911,7 @@ namespace libtorrent
}
}
storage_interface* default_storage_constructor(torrent_info const& ti
storage_interface* default_storage_constructor(boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path, file_pool& fp)
{
return new storage(ti, path, fp);
@ -1027,7 +1025,7 @@ namespace libtorrent
piece_manager::piece_manager(
boost::shared_ptr<void> const& torrent
, torrent_info const& ti
, boost::intrusive_ptr<torrent_info const> ti
, fs::path const& save_path
, file_pool& fp
, disk_io_thread& io
@ -1037,7 +1035,7 @@ namespace libtorrent
, m_fill_mode(true)
, m_info(ti)
, m_save_path(complete(save_path))
, m_allocating(false)
, m_storage_constructor(sc)
, m_io_thread(io)
, m_torrent(torrent)
{
@ -1140,7 +1138,7 @@ namespace libtorrent
int slot = m_piece_to_slot[piece];
assert(slot != has_no_slot);
return m_storage->hash_for_slot(slot, ph, m_info.piece_size(piece));
return m_storage->hash_for_slot(slot, ph, m_info->piece_size(piece));
}
void piece_manager::release_files_impl()
@ -1200,7 +1198,7 @@ namespace libtorrent
int piece_manager::slot_for_piece(int piece_index) const
{
assert(piece_index >= 0 && piece_index < m_info.num_pieces());
assert(piece_index >= 0 && piece_index < m_info->num_pieces());
return m_piece_to_slot[piece_index];
}
@ -1211,13 +1209,13 @@ namespace libtorrent
try
{
assert(slot_index >= 0);
assert(slot_index < m_info.num_pieces());
assert(slot_index < m_info->num_pieces());
assert(block_size > 0);
adler32_crc crc;
std::vector<char> buf(block_size);
int num_blocks = static_cast<int>(m_info.piece_size(slot_index)) / block_size;
int last_block_size = static_cast<int>(m_info.piece_size(slot_index)) % block_size;
int num_blocks = static_cast<int>(m_info->piece_size(slot_index)) / block_size;
int last_block_size = static_cast<int>(m_info->piece_size(slot_index)) % block_size;
if (last_block_size == 0) last_block_size = block_size;
for (int i = 0; i < num_blocks-1; ++i)
@ -1310,11 +1308,11 @@ namespace libtorrent
{
// INVARIANT_CHECK;
assert((int)have_pieces.size() == m_info.num_pieces());
assert((int)have_pieces.size() == m_info->num_pieces());
const int piece_size = static_cast<int>(m_info.piece_length());
const int last_piece_size = static_cast<int>(m_info.piece_size(
m_info.num_pieces() - 1));
const int piece_size = static_cast<int>(m_info->piece_length());
const int last_piece_size = static_cast<int>(m_info->piece_size(
m_info->num_pieces() - 1));
assert((int)piece_data.size() >= last_piece_size);
@ -1470,7 +1468,7 @@ namespace libtorrent
INVARIANT_CHECK;
assert(m_info.piece_length() > 0);
assert(m_info->piece_length() > 0);
m_compact_mode = compact_mode;
@ -1480,13 +1478,13 @@ namespace libtorrent
// by check_pieces.
// m_storage->shuffle();
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
m_slot_to_piece.resize(m_info.num_pieces(), unallocated);
m_piece_to_slot.resize(m_info->num_pieces(), has_no_slot);
m_slot_to_piece.resize(m_info->num_pieces(), unallocated);
m_free_slots.clear();
m_unallocated_slots.clear();
pieces.clear();
pieces.resize(m_info.num_pieces(), false);
pieces.resize(m_info->num_pieces(), false);
num_pieces = 0;
// if we have fast-resume info
@ -1591,7 +1589,7 @@ namespace libtorrent
return std::make_pair(false, 1.f);
}
if (int(m_unallocated_slots.size()) == m_info.num_pieces()
if (int(m_unallocated_slots.size()) == m_info->num_pieces()
&& !m_fill_mode)
{
// if there is not a single file on disk, just
@ -1633,8 +1631,8 @@ namespace libtorrent
assert(!m_fill_mode);
std::vector<int>().swap(m_unallocated_slots);
std::fill(m_slot_to_piece.begin(), m_slot_to_piece.end(), int(unassigned));
m_free_slots.resize(m_info.num_pieces());
for (int i = 0; i < m_info.num_pieces(); ++i)
m_free_slots.resize(m_info->num_pieces());
for (int i = 0; i < m_info->num_pieces(); ++i)
m_free_slots[i] = i;
}
@ -1654,15 +1652,15 @@ namespace libtorrent
if (m_hash_to_piece.empty())
{
m_current_slot = 0;
for (int i = 0; i < m_info.num_pieces(); ++i)
for (int i = 0; i < m_info->num_pieces(); ++i)
{
m_hash_to_piece.insert(std::make_pair(m_info.hash_for_piece(i), i));
m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i));
}
std::fill(pieces.begin(), pieces.end(), false);
}
m_piece_data.resize(int(m_info.piece_length()));
int piece_size = int(m_info.piece_size(m_current_slot));
m_piece_data.resize(int(m_info->piece_length()));
int piece_size = int(m_info->piece_size(m_current_slot));
int num_read = m_storage->read(&m_piece_data[0]
, m_current_slot, 0, piece_size);
@ -1865,9 +1863,9 @@ namespace libtorrent
{
// find the file that failed, and skip all the blocks in that file
size_type file_offset = 0;
size_type current_offset = m_current_slot * m_info.piece_length();
for (torrent_info::file_iterator i = m_info.begin_files(true);
i != m_info.end_files(true); ++i)
size_type current_offset = m_current_slot * m_info->piece_length();
for (torrent_info::file_iterator i = m_info->begin_files(true);
i != m_info->end_files(true); ++i)
{
file_offset += i->size;
if (file_offset > current_offset) break;
@ -1875,8 +1873,8 @@ namespace libtorrent
assert(file_offset > current_offset);
int skip_blocks = static_cast<int>(
(file_offset - current_offset + m_info.piece_length() - 1)
/ m_info.piece_length());
(file_offset - current_offset + m_info->piece_length() - 1)
/ m_info->piece_length());
for (int i = m_current_slot; i < m_current_slot + skip_blocks; ++i)
{
@ -1889,9 +1887,9 @@ namespace libtorrent
}
++m_current_slot;
if (m_current_slot >= m_info.num_pieces())
if (m_current_slot >= m_info->num_pieces())
{
assert(m_current_slot == m_info.num_pieces());
assert(m_current_slot == m_info->num_pieces());
// clear the memory we've been using
std::vector<char>().swap(m_piece_data);
@ -1903,7 +1901,7 @@ namespace libtorrent
assert(num_pieces == std::count(pieces.begin(), pieces.end(), true));
return std::make_pair(false, (float)m_current_slot / m_info.num_pieces());
return std::make_pair(false, (float)m_current_slot / m_info->num_pieces());
}
int piece_manager::allocate_slot_for_piece(int piece_index)
@ -1945,7 +1943,7 @@ namespace libtorrent
// special case to make sure we don't use the last slot
// when we shouldn't, since it's smaller than ordinary slots
if (*iter == m_info.num_pieces() - 1 && piece_index != *iter)
if (*iter == m_info->num_pieces() - 1 && piece_index != *iter)
{
if (m_free_slots.size() == 1)
allocate_slots(1);
@ -2050,7 +2048,7 @@ namespace libtorrent
}
else if (m_fill_mode)
{
int piece_size = int(m_info.piece_size(pos));
int piece_size = int(m_info->piece_size(pos));
int offset = 0;
for (; piece_size > 0; piece_size -= stack_buffer_size
, offset += stack_buffer_size)
@ -2076,8 +2074,8 @@ namespace libtorrent
boost::recursive_mutex::scoped_lock lock(m_mutex);
if (m_piece_to_slot.empty()) return;
assert((int)m_piece_to_slot.size() == m_info.num_pieces());
assert((int)m_slot_to_piece.size() == m_info.num_pieces());
assert((int)m_piece_to_slot.size() == m_info->num_pieces());
assert((int)m_slot_to_piece.size() == m_info->num_pieces());
for (std::vector<int>::const_iterator i = m_free_slots.begin();
i != m_free_slots.end(); ++i)
@ -2099,7 +2097,7 @@ namespace libtorrent
== m_unallocated_slots.end());
}
for (int i = 0; i < m_info.num_pieces(); ++i)
for (int i = 0; i < m_info->num_pieces(); ++i)
{
// Check domain of piece_to_slot's elements
if (m_piece_to_slot[i] != has_no_slot)
@ -2187,7 +2185,7 @@ namespace libtorrent
s << "index\tslot\tpiece\n";
for (int i = 0; i < m_info.num_pieces(); ++i)
for (int i = 0; i < m_info->num_pieces(); ++i)
{
s << i << "\t" << m_slot_to_piece[i] << "\t";
s << m_piece_to_slot[i] << "\n";

View File

@ -150,7 +150,7 @@ namespace libtorrent
torrent::torrent(
session_impl& ses
, aux::checker_impl& checker
, torrent_info const& tf
, boost::intrusive_ptr<torrent_info> tf
, fs::path const& save_path
, tcp::endpoint const& net_interface
, bool compact_mode
@ -181,7 +181,7 @@ namespace libtorrent
, m_ses(ses)
, m_checker(checker)
, m_picker(0)
, m_trackers(m_torrent_file.trackers())
, m_trackers(m_torrent_file->trackers())
, m_last_working_tracker(-1)
, m_currently_trying_tracker(0)
, m_failed_trackers(0)
@ -221,7 +221,7 @@ namespace libtorrent
, int block_size
, storage_constructor_type sc
, bool paused)
: m_torrent_file(info_hash)
: m_torrent_file(new torrent_info(info_hash))
, m_abort(false)
, m_paused(paused)
, m_just_paused(false)
@ -277,7 +277,7 @@ namespace libtorrent
if (tracker_url)
{
m_trackers.push_back(announce_entry(tracker_url));
m_torrent_file.add_tracker(tracker_url);
m_torrent_file->add_tracker(tracker_url);
}
m_policy.reset(new policy(this));
@ -286,7 +286,7 @@ namespace libtorrent
void torrent::start()
{
boost::weak_ptr<torrent> self(shared_from_this());
if (m_torrent_file.is_valid()) init();
if (m_torrent_file->is_valid()) init();
m_announce_timer.expires_from_now(seconds(1));
m_announce_timer.async_wait(m_ses.m_strand.wrap(
bind(&torrent::on_announce_disp, self, _1)));
@ -296,7 +296,7 @@ namespace libtorrent
bool torrent::should_announce_dht() const
{
// don't announce private torrents
if (m_torrent_file.is_valid() && m_torrent_file.priv()) return false;
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
if (m_trackers.empty()) return true;
@ -334,7 +334,7 @@ namespace libtorrent
std::string torrent::name() const
{
if (valid_metadata()) return m_torrent_file.name();
if (valid_metadata()) return m_torrent_file->name();
if (m_name) return *m_name;
return "";
}
@ -350,22 +350,22 @@ namespace libtorrent
// shared_from_this()
void torrent::init()
{
assert(m_torrent_file.is_valid());
assert(m_torrent_file.num_files() > 0);
assert(m_torrent_file.total_size() >= 0);
assert(m_torrent_file->is_valid());
assert(m_torrent_file->num_files() > 0);
assert(m_torrent_file->total_size() >= 0);
m_have_pieces.resize(m_torrent_file.num_pieces(), false);
m_have_pieces.resize(m_torrent_file->num_pieces(), false);
// the shared_from_this() will create an intentional
// cycle of ownership, se the hpp file for description.
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor);
m_storage = m_owning_storage.get();
m_block_size = calculate_block_size(m_torrent_file, m_default_block_size);
m_block_size = calculate_block_size(*m_torrent_file, m_default_block_size);
m_picker.reset(new piece_picker(
static_cast<int>(m_torrent_file.piece_length() / m_block_size)
, static_cast<int>((m_torrent_file.total_size()+m_block_size-1)/m_block_size)));
static_cast<int>(m_torrent_file->piece_length() / m_block_size)
, static_cast<int>((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
std::vector<std::string> const& url_seeds = m_torrent_file.url_seeds();
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
, m_web_seeds.begin()));
}
@ -393,7 +393,7 @@ namespace libtorrent
{
boost::weak_ptr<torrent> self(shared_from_this());
if (!m_torrent_file.priv())
if (!m_torrent_file->priv())
{
// announce on local network every 5 minutes
m_announce_timer.expires_from_now(minutes(5));
@ -401,7 +401,7 @@ namespace libtorrent
bind(&torrent::on_announce_disp, self, _1)));
// announce with the local discovery service
m_ses.announce_lsd(m_torrent_file.info_hash());
m_ses.announce_lsd(m_torrent_file->info_hash());
}
else
{
@ -419,7 +419,7 @@ namespace libtorrent
// TODO: There should be a way to abort an announce operation on the dht.
// when the torrent is destructed
assert(m_ses.m_external_listen_port > 0);
m_ses.m_dht->announce(m_torrent_file.info_hash()
m_ses.m_dht->announce(m_torrent_file->info_hash()
, m_ses.m_external_listen_port
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
}
@ -465,7 +465,7 @@ namespace libtorrent
{
INVARIANT_CHECK;
if (m_torrent_file.trackers().empty()) return false;
if (m_torrent_file->trackers().empty()) return false;
if (m_just_paused)
{
@ -615,7 +615,7 @@ namespace libtorrent
// if we don't have the metadata yet, we
// cannot tell how big the torrent is.
if (!valid_metadata()) return -1;
return m_torrent_file.total_size()
return m_torrent_file->total_size()
- quantized_bytes_done();
}
@ -625,23 +625,23 @@ namespace libtorrent
if (!valid_metadata()) return 0;
if (m_torrent_file.num_pieces() == 0)
if (m_torrent_file->num_pieces() == 0)
return 0;
if (is_seed()) return m_torrent_file.total_size();
if (is_seed()) return m_torrent_file->total_size();
const int last_piece = m_torrent_file.num_pieces() - 1;
const int last_piece = m_torrent_file->num_pieces() - 1;
size_type total_done
= m_num_pieces * m_torrent_file.piece_length();
= m_num_pieces * m_torrent_file->piece_length();
// if we have the last piece, we have to correct
// the amount we have, since the first calculation
// assumed all pieces were of equal size
if (m_have_pieces[last_piece])
{
int corr = m_torrent_file.piece_size(last_piece)
- m_torrent_file.piece_length();
int corr = m_torrent_file->piece_size(last_piece)
- m_torrent_file->piece_length();
total_done += corr;
}
return total_done;
@ -654,42 +654,42 @@ namespace libtorrent
{
INVARIANT_CHECK;
if (!valid_metadata() || m_torrent_file.num_pieces() == 0)
if (!valid_metadata() || m_torrent_file->num_pieces() == 0)
return tuple<size_type, size_type>(0,0);
const int last_piece = m_torrent_file.num_pieces() - 1;
const int last_piece = m_torrent_file->num_pieces() - 1;
if (is_seed())
return make_tuple(m_torrent_file.total_size()
, m_torrent_file.total_size());
return make_tuple(m_torrent_file->total_size()
, m_torrent_file->total_size());
size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered())
* m_torrent_file.piece_length();
* m_torrent_file->piece_length();
size_type total_done
= m_num_pieces * m_torrent_file.piece_length();
assert(m_num_pieces < m_torrent_file.num_pieces());
= m_num_pieces * m_torrent_file->piece_length();
assert(m_num_pieces < m_torrent_file->num_pieces());
// if we have the last piece, we have to correct
// the amount we have, since the first calculation
// assumed all pieces were of equal size
if (m_have_pieces[last_piece])
{
int corr = m_torrent_file.piece_size(last_piece)
- m_torrent_file.piece_length();
int corr = m_torrent_file->piece_size(last_piece)
- m_torrent_file->piece_length();
total_done += corr;
if (m_picker->piece_priority(last_piece) != 0)
wanted_done += corr;
}
assert(total_done <= m_torrent_file.total_size());
assert(wanted_done <= m_torrent_file.total_size());
assert(total_done <= m_torrent_file->total_size());
assert(wanted_done <= m_torrent_file->total_size());
const std::vector<piece_picker::downloading_piece>& dl_queue
= m_picker->get_download_queue();
const int blocks_per_piece = static_cast<int>(
m_torrent_file.piece_length() / m_block_size);
m_torrent_file->piece_length() / m_block_size);
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
dl_queue.begin(); i != dl_queue.end(); ++i)
@ -722,15 +722,15 @@ namespace libtorrent
== piece_picker::block_info::state_finished)
{
corr -= m_block_size;
corr += m_torrent_file.piece_size(last_piece) % m_block_size;
corr += m_torrent_file->piece_size(last_piece) % m_block_size;
}
total_done += corr;
if (m_picker->piece_priority(index) != 0)
wanted_done += corr;
}
assert(total_done <= m_torrent_file.total_size());
assert(wanted_done <= m_torrent_file.total_size());
assert(total_done <= m_torrent_file->total_size());
assert(wanted_done <= m_torrent_file->total_size());
std::map<piece_block, int> downloading_piece;
for (const_peer_iterator i = begin(); i != end(); ++i)
@ -760,10 +760,10 @@ namespace libtorrent
}
#ifndef NDEBUG
assert(p->bytes_downloaded <= p->full_block_bytes);
int last_piece = m_torrent_file.num_pieces() - 1;
int last_piece = m_torrent_file->num_pieces() - 1;
if (p->piece_index == last_piece
&& p->block_index == m_torrent_file.piece_size(last_piece) / block_size())
assert(p->full_block_bytes == m_torrent_file.piece_size(last_piece) % block_size());
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
assert(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
else
assert(p->full_block_bytes == block_size());
#endif
@ -779,7 +779,7 @@ namespace libtorrent
#ifndef NDEBUG
if (total_done >= m_torrent_file.total_size())
if (total_done >= m_torrent_file->total_size())
{
std::copy(m_have_pieces.begin(), m_have_pieces.end()
, std::ostream_iterator<bool>(std::cerr, " "));
@ -810,8 +810,8 @@ namespace libtorrent
}
assert(total_done <= m_torrent_file.total_size());
assert(wanted_done <= m_torrent_file.total_size());
assert(total_done <= m_torrent_file->total_size());
assert(wanted_done <= m_torrent_file->total_size());
#endif
@ -908,14 +908,14 @@ namespace libtorrent
// think that it has received all of it until this function
// resets the download queue. So, we cannot do the
// invariant check here since it assumes:
// (total_done == m_torrent_file.total_size()) => is_seed()
// (total_done == m_torrent_file->total_size()) => is_seed()
// INVARIANT_CHECK;
assert(m_storage);
assert(m_storage->refcount() > 0);
assert(m_picker.get());
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
if (m_ses.m_alerts.should_post(alert::info))
{
@ -924,7 +924,7 @@ namespace libtorrent
m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index, s.str()));
}
// increase the total amount of failed bytes
m_total_failed_bytes += m_torrent_file.piece_size(index);
m_total_failed_bytes += m_torrent_file->piece_size(index);
std::vector<void*> downloaders;
m_picker->get_downloaders(downloaders, index);
@ -1047,7 +1047,7 @@ namespace libtorrent
// INVARIANT_CHECK;
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
std::vector<void*> downloaders;
m_picker->get_downloaders(downloaders, index);
@ -1090,7 +1090,7 @@ namespace libtorrent
if (is_seed())
{
m_picker.reset();
m_torrent_file.seed_free();
m_torrent_file->seed_free();
}
}
@ -1124,7 +1124,7 @@ namespace libtorrent
// this call is only valid on torrents with metadata
assert(m_picker.get());
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
bool filter_updated = m_picker->set_piece_priority(index, priority);
if (filter_updated) update_peer_interest();
@ -1140,7 +1140,7 @@ namespace libtorrent
// this call is only valid on torrents with metadata
assert(m_picker.get());
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
return m_picker->piece_priority(index);
}
@ -1176,7 +1176,7 @@ namespace libtorrent
if (is_seed())
{
pieces.clear();
pieces.resize(m_torrent_file.num_pieces(), 1);
pieces.resize(m_torrent_file->num_pieces(), 1);
return;
}
@ -1201,20 +1201,20 @@ namespace libtorrent
// the bitmask need to have exactly one bit for every file
// in the torrent
assert(int(files.size()) == m_torrent_file.num_files());
assert(int(files.size()) == m_torrent_file->num_files());
size_type position = 0;
if (m_torrent_file.num_pieces() == 0) return;
if (m_torrent_file->num_pieces() == 0) return;
int piece_length = m_torrent_file.piece_length();
int piece_length = m_torrent_file->piece_length();
// initialize the piece priorities to 0, then only allow
// setting higher priorities
std::vector<int> pieces(m_torrent_file.num_pieces(), 0);
std::vector<int> pieces(m_torrent_file->num_pieces(), 0);
for (int i = 0; i < int(files.size()); ++i)
{
size_type start = position;
size_type size = m_torrent_file.file_at(i).size;
size_type size = m_torrent_file->file_at(i).size;
if (size == 0) continue;
position += size;
// mark all pieces of the file with this file's priority
@ -1250,7 +1250,7 @@ namespace libtorrent
// this call is only valid on torrents with metadata
assert(m_picker.get());
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
m_picker->set_piece_priority(index, filter ? 1 : 0);
update_peer_interest();
@ -1287,7 +1287,7 @@ namespace libtorrent
assert(m_picker.get());
assert(index >= 0);
assert(index < m_torrent_file.num_pieces());
assert(index < m_torrent_file->num_pieces());
return m_picker->piece_priority(index) == 0;
}
@ -1301,7 +1301,7 @@ namespace libtorrent
if (is_seed())
{
bitmask.clear();
bitmask.resize(m_torrent_file.num_pieces(), false);
bitmask.resize(m_torrent_file->num_pieces(), false);
return;
}
@ -1318,20 +1318,20 @@ namespace libtorrent
// the bitmask need to have exactly one bit for every file
// in the torrent
assert((int)bitmask.size() == m_torrent_file.num_files());
assert((int)bitmask.size() == m_torrent_file->num_files());
size_type position = 0;
if (m_torrent_file.num_pieces())
if (m_torrent_file->num_pieces())
{
int piece_length = m_torrent_file.piece_length();
int piece_length = m_torrent_file->piece_length();
// mark all pieces as filtered, then clear the bits for files
// that should be downloaded
std::vector<bool> piece_filter(m_torrent_file.num_pieces(), true);
std::vector<bool> piece_filter(m_torrent_file->num_pieces(), true);
for (int i = 0; i < (int)bitmask.size(); ++i)
{
size_type start = position;
position += m_torrent_file.file_at(i).size;
position += m_torrent_file->file_at(i).size;
// is the file selected for download?
if (!bitmask[i])
{
@ -1366,7 +1366,7 @@ namespace libtorrent
m_next_request = time_now() + seconds(tracker_retry_delay_max);
tracker_request req;
req.info_hash = m_torrent_file.info_hash();
req.info_hash = m_torrent_file->info_hash();
req.pid = m_ses.get_peer_id();
req.downloaded = m_stat.total_payload_download();
req.uploaded = m_stat.total_payload_upload();
@ -1890,8 +1890,8 @@ namespace libtorrent
{
INVARIANT_CHECK;
assert(!m_torrent_file.is_valid());
m_torrent_file.parse_info_section(metadata);
assert(!m_torrent_file->is_valid());
m_torrent_file->parse_info_section(metadata);
init();
@ -1901,12 +1901,12 @@ namespace libtorrent
new aux::piece_checker_data);
d->torrent_ptr = shared_from_this();
d->save_path = m_save_path;
d->info_hash = m_torrent_file.info_hash();
d->info_hash = m_torrent_file->info_hash();
// add the torrent to the queue to be checked
m_checker.m_torrents.push_back(d);
typedef session_impl::torrent_map torrent_map;
torrent_map::iterator i = m_ses.m_torrents.find(
m_torrent_file.info_hash());
m_torrent_file->info_hash());
assert(i != m_ses.m_torrents.end());
m_ses.m_torrents.erase(i);
// and notify the thread that it got another
@ -2291,7 +2291,7 @@ namespace libtorrent
if (is_seed())
{
m_picker.reset();
m_torrent_file.seed_free();
m_torrent_file->seed_free();
}
if (!m_connections_initialized)
@ -2374,7 +2374,7 @@ namespace libtorrent
torrent_handle torrent::get_handle() const
{
return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash());
return torrent_handle(&m_ses, &m_checker, m_torrent_file->info_hash());
}
session_settings const& torrent::settings() const
@ -2417,7 +2417,7 @@ namespace libtorrent
if (valid_metadata())
{
assert(m_abort || int(m_have_pieces.size()) == m_torrent_file.num_pieces());
assert(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces());
}
else
{
@ -2425,12 +2425,12 @@ namespace libtorrent
}
size_type total_done = quantized_bytes_done();
if (m_torrent_file.is_valid())
if (m_torrent_file->is_valid())
{
if (is_seed())
assert(total_done == m_torrent_file.total_size());
assert(total_done == m_torrent_file->total_size());
else
assert(total_done != m_torrent_file.total_size());
assert(total_done != m_torrent_file->total_size());
}
else
{
@ -2441,7 +2441,7 @@ namespace libtorrent
assert(m_num_pieces
== std::count(m_have_pieces.begin(), m_have_pieces.end(), true));
assert(!valid_metadata() || m_block_size > 0);
assert(!valid_metadata() || (m_torrent_file.piece_length() % m_block_size) == 0);
assert(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
// if (is_seed()) assert(m_picker.get() == 0);
}
#endif
@ -2678,7 +2678,7 @@ namespace libtorrent
assert(m_storage);
assert(m_storage->refcount() > 0);
assert(piece_index >= 0);
assert(piece_index < m_torrent_file.num_pieces());
assert(piece_index < m_torrent_file->num_pieces());
assert(piece_index < (int)m_have_pieces.size());
m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
@ -2690,7 +2690,7 @@ namespace libtorrent
{
sha1_hash h(j.str);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
f(m_torrent_file.hash_for_piece(j.piece) == h);
f(m_torrent_file->hash_for_piece(j.piece) == h);
}
const tcp::endpoint& torrent::current_tracker() const
@ -2706,12 +2706,12 @@ namespace libtorrent
assert(valid_metadata());
fp.clear();
fp.resize(m_torrent_file.num_files(), 0.f);
fp.resize(m_torrent_file->num_files(), 0.f);
for (int i = 0; i < m_torrent_file.num_files(); ++i)
for (int i = 0; i < m_torrent_file->num_files(); ++i)
{
peer_request ret = m_torrent_file.map_file(i, 0, 0);
size_type size = m_torrent_file.file_at(i).size;
peer_request ret = m_torrent_file->map_file(i, 0, 0);
size_type size = m_torrent_file->file_at(i).size;
// zero sized files are considered
// 100% done all the time
@ -2724,7 +2724,7 @@ namespace libtorrent
size_type done = 0;
while (size > 0)
{
size_type bytes_step = (std::min)(m_torrent_file.piece_size(ret.piece)
size_type bytes_step = (std::min)(m_torrent_file->piece_size(ret.piece)
- ret.start, size);
if (m_have_pieces[ret.piece]) done += bytes_step;
++ret.piece;
@ -2733,7 +2733,7 @@ namespace libtorrent
}
assert(size == 0);
fp[i] = static_cast<float>(done) / m_torrent_file.file_at(i).size;
fp[i] = static_cast<float>(done) / m_torrent_file->file_at(i).size;
}
}
@ -2820,21 +2820,21 @@ namespace libtorrent
// fill in status that depends on metadata
st.total_wanted = m_torrent_file.total_size();
st.total_wanted = m_torrent_file->total_size();
if (m_picker.get() && (m_picker->num_filtered() > 0
|| m_picker->num_have_filtered() > 0))
{
int filtered_pieces = m_picker->num_filtered()
+ m_picker->num_have_filtered();
int last_piece_index = m_torrent_file.num_pieces() - 1;
int last_piece_index = m_torrent_file->num_pieces() - 1;
if (m_picker->piece_priority(last_piece_index) == 0)
{
st.total_wanted -= m_torrent_file.piece_size(last_piece_index);
st.total_wanted -= m_torrent_file->piece_size(last_piece_index);
--filtered_pieces;
}
st.total_wanted -= filtered_pieces * m_torrent_file.piece_length();
st.total_wanted -= filtered_pieces * m_torrent_file->piece_length();
}
assert(st.total_wanted >= st.total_wanted_done);
@ -2852,7 +2852,7 @@ namespace libtorrent
}
else if (is_seed())
{
assert(st.total_done == m_torrent_file.total_size());
assert(st.total_done == m_torrent_file->total_size());
st.state = torrent_status::seeding;
}
else if (st.total_wanted_done == st.total_wanted)

View File

@ -323,7 +323,13 @@ try
#endif
{
using namespace libtorrent::detail;
if (e) return;
if (e)
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string() << " *** on_reply aborted: " << e.message() << std::endl;
#endif
return;
}
// parse out the url for the device
@ -843,9 +849,16 @@ void upnp::on_upnp_map_response(asio::error_code const& e
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== error while adding portmap: " << p.message() << std::endl;
<< " <== error while adding portmap: " << p.status_code() << " " << p.message() << std::endl;
#endif
m_devices.erase(d);
for (int i = 0; i < num_mappings; ++i)
{
if (d.mapping[i].need_update)
{
map_port(d, i);
return;
}
}
return;
}

View File

@ -69,9 +69,6 @@ namespace libtorrent
{
INVARIANT_CHECK;
// we always prefer downloading entire
// pieces from web seeds
prefer_whole_pieces(true);
// we want large blocks as well, so
// we can request more bytes at once
request_large_blocks(true);
@ -80,6 +77,10 @@ namespace libtorrent
shared_ptr<torrent> tor = t.lock();
assert(tor);
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();
// we always prefer downloading 1 MB chunks
// from web seeds
prefer_whole_pieces((1024 * 1024) / tor->torrent_file().piece_length());
// multiply with the blocks per piece since that many requests are
// merged into one http request
@ -178,13 +179,16 @@ namespace libtorrent
int size = r.length;
const int block_size = t->block_size();
const int piece_size = t->torrent_file().piece_length();
peer_request pr;
while (size > 0)
{
int request_size = (std::min)(block_size, size);
peer_request pr = {r.piece, r.start + r.length - size
, request_size};
int request_offset = r.start + r.length - size;
pr.start = request_offset % piece_size;
pr.length = (std::min)(block_size, size);
pr.piece = r.piece + request_offset / piece_size;
m_requests.push_back(pr);
size -= request_size;
size -= pr.length;
}
proxy_settings const& ps = m_ses.web_seed_proxy();
@ -477,8 +481,11 @@ namespace libtorrent
peer_request front_request = m_requests.front();
if (in_range.piece != front_request.piece
|| in_range.start > front_request.start + int(m_piece.size()))
size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start;
size_type re = rs + in_range.length;
size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start;
size_type fe = fs + front_request.length;
if (fs < rs || fe > re)
{
throw std::runtime_error("invalid range in HTTP response");
}