lt sync 2388

This commit is contained in:
Andrew Resch 2008-06-07 18:58:33 +00:00
parent bf00795050
commit 7107413d0e
19 changed files with 408 additions and 240 deletions

View File

@ -13,7 +13,7 @@ object pieces(torrent_status const& s)
{
list result;
for (bitfield::const_iterator i(s.pieces->begin()), e(s.pieces->end()); i != e; ++i)
for (bitfield::const_iterator i(s.pieces.begin()), e(s.pieces.end()); i != e; ++i)
result.append(*i);
return result;

View File

@ -209,7 +209,7 @@ namespace libtorrent
void write_not_interested();
void write_request(peer_request const& r);
void write_cancel(peer_request const& r);
void write_bitfield(bitfield const& bits);
void write_bitfield();
void write_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake();

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/version.hpp>
#if defined(__GNUC__) && __GNUC__ >= 4
@ -81,7 +82,12 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_BSD
#endif
// should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY && BOOST_VERSION >= 103400
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif
#endif // TORRENT_CONFIG_HPP_INCLUDED

View File

@ -129,18 +129,13 @@ namespace libtorrent
boost::int16_t requested;
};
piece_picker(int blocks_per_piece
, int total_num_blocks);
piece_picker();
void get_availability(std::vector<int>& avail) const;
void sequential_download(bool sd);
bool sequential_download() const { return m_sequential_download >= 0; }
// the vector tells which pieces we already have
// and which we don't have.
void init(bitfield const& pieces);
// increases the peer count for the given piece
// (is used when a HAVE message is received)
void inc_refcount(int index);
@ -164,6 +159,17 @@ namespace libtorrent
// we are not interested in this piece anymore
// (i.e. we don't have to maintain a refcount)
void we_have(int index);
void we_dont_have(int index);
void init(int blocks_per_piece, int total_num_blocks);
int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < int(m_piece_map.size()));
return m_piece_map[index].index == piece_pos::we_have_index;
}
// sets the priority of a piece.
// returns true if the priority was changed from 0 to non-0
@ -276,6 +282,8 @@ namespace libtorrent
// the number of filtered pieces we already have
int num_have_filtered() const { return m_num_have_filtered; }
int num_have() const { return m_num_have; }
#ifndef NDEBUG
// used in debug mode
void verify_priority(int start, int end, int prio) const;
@ -350,6 +358,7 @@ namespace libtorrent
bool have() const { return index == we_have_index; }
void set_have() { index = we_have_index; TORRENT_ASSERT(have()); }
void set_not_have() { index = 0; TORRENT_ASSERT(!have()); }
bool filtered() const { return piece_priority == filter_priority; }
void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
@ -466,10 +475,6 @@ namespace libtorrent
// if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces.
mutable bool m_dirty;
#ifndef NDEBUG
bool m_files_checked_called;
#endif
};
inline int piece_picker::blocks_in_piece(int index) const

View File

@ -129,7 +129,7 @@ namespace libtorrent
, resume_data(0)
, storage_mode(storage_mode_sparse)
, paused(true)
, auto_managed(false)
, auto_managed(true)
, duplicate_is_error(false)
, storage(sc)
, userdata(0)

View File

@ -149,6 +149,7 @@ namespace libtorrent
void init();
void on_resume_data_checked(int ret, disk_io_job const& j);
void on_force_recheck(int ret, disk_io_job const& j);
void on_piece_checked(int ret, disk_io_job const& j);
void files_checked();
void start_checking();
@ -180,6 +181,7 @@ namespace libtorrent
std::string name() const;
stat statistics() const { return m_stat; }
void add_stats(stat const& s) { m_stat += s; }
size_type bytes_left() const;
boost::tuples::tuple<size_type, size_type> bytes_done() const;
size_type quantized_bytes_done() const;
@ -190,6 +192,7 @@ namespace libtorrent
void pause();
void resume();
bool is_paused() const { return m_paused; }
void force_recheck();
void save_resume_data();
bool is_auto_managed() const { return m_auto_managed; }
@ -377,14 +380,15 @@ namespace libtorrent
// returns true if we have downloaded the given piece
bool have_piece(int index) const
{
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
return m_have_pieces[index];
return has_picker()?m_picker->have_piece(index):true;
}
bitfield const& pieces() const
{ return m_have_pieces; }
int num_pieces() const { return m_num_pieces; }
int num_have() const
{
return has_picker()
?m_picker->num_have()
:m_torrent_file->num_pieces();
}
// when we get a have message, this is called for that piece
void peer_has(int index)
@ -392,7 +396,6 @@ namespace libtorrent
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->inc_refcount(index);
}
#ifndef NDEBUG
@ -439,7 +442,6 @@ namespace libtorrent
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->dec_refcount(index);
}
#ifndef NDEBUG
@ -506,7 +508,9 @@ namespace libtorrent
bool is_seed() const
{
return valid_metadata()
&& m_num_pieces == m_torrent_file->num_pieces();
&& (!m_picker
|| m_state == torrent_status::seeding
|| m_picker->num_have() == m_picker->num_pieces());
}
// this is true if we have all the pieces that we want
@ -514,7 +518,7 @@ namespace libtorrent
{
if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_pieces()
- m_num_pieces - m_picker->num_filtered() == 0;
- m_picker->num_have() - m_picker->num_filtered() == 0;
}
fs::path save_path() const;
@ -740,9 +744,6 @@ namespace libtorrent
std::vector<announce_entry> m_trackers;
// this is an index into m_trackers
// the bitmask that says which pieces we have
bitfield m_have_pieces;
// the number of bytes that has been
// downloaded that failed the hash-test
size_type m_total_failed_bytes;
@ -781,11 +782,6 @@ namespace libtorrent
float m_progress;
// the number of pieces we have. The same as
// std::accumulate(m_have_pieces.begin(),
// m_have_pieces.end(), 0)
int m_num_pieces;
// the upload/download ratio that each peer
// tries to maintain.
// 0 is infinite
@ -908,9 +904,14 @@ namespace libtorrent
// has been initialized with files_checked().
bool m_connections_initialized:1;
#ifndef NDEBUG
// is set to true every time there is an incoming
// connection to this torrent
bool m_has_incoming:1;
// this is set to true when the files are checked
// before the files are checked, we don't try to
// connect to peers
bool m_files_checked:1;
#endif
};
inline ptime torrent::next_announce() const

View File

@ -100,7 +100,6 @@ namespace libtorrent
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, pieces(0)
, num_pieces(0)
, total_done(0)
, total_wanted_done(0)
@ -120,6 +119,7 @@ namespace libtorrent
, seeding_time(0)
, seed_rank(0)
, last_scrape(0)
, has_incoming(false)
{}
enum state_t
@ -200,7 +200,7 @@ namespace libtorrent
// we potentially could connect to
int connect_candidates;
bitfield const* pieces;
bitfield pieces;
// this is the number of pieces the client has
// downloaded. it is equal to:
@ -266,6 +266,10 @@ namespace libtorrent
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
// true if there are incoming connections to this
// torrent
bool has_incoming;
};
struct TORRENT_EXPORT block_info
@ -341,6 +345,7 @@ namespace libtorrent
bool is_paused() const;
void pause() const;
void resume() const;
void force_recheck() const;
void save_resume_data() const;
bool is_auto_managed() const;

View File

@ -173,6 +173,9 @@ namespace libtorrent
// response. used to know where in the buffer the
// next response starts
int m_received_body;
// position in the current range response
int m_range_pos;
};
}

View File

@ -245,7 +245,7 @@ namespace libtorrent
{
boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(t);
write_bitfield(t->pieces());
write_bitfield();
#ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port);
@ -1416,7 +1416,7 @@ namespace libtorrent
send_buffer(msg, sizeof(msg));
}
void bt_peer_connection::write_bitfield(bitfield const& bits)
void bt_peer_connection::write_bitfield()
{
INVARIANT_CHECK;
@ -1426,7 +1426,7 @@ namespace libtorrent
TORRENT_ASSERT(t->valid_metadata());
// in this case, have_all or have_none should be sent instead
TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_pieces() != 0);
TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_have() != 0);
if (m_supports_fast && t->is_seed())
{
@ -1434,13 +1434,13 @@ namespace libtorrent
send_allowed_set();
return;
}
else if (m_supports_fast && t->num_pieces() == 0)
else if (m_supports_fast && t->num_have() == 0)
{
write_have_none();
send_allowed_set();
return;
}
else if (t->num_pieces() == 0)
else if (t->num_have() == 0)
{
// don't send a bitfield if we don't have any pieces
#ifndef NDEBUG
@ -1449,14 +1449,11 @@ namespace libtorrent
return;
}
int num_pieces = bits.size();
int num_pieces = t->torrent_file().num_pieces();
int lazy_pieces[50];
int num_lazy_pieces = 0;
int lazy_piece = 0;
TORRENT_ASSERT(t->is_seed() == (bits.count()
== num_pieces));
if (t->is_seed() && m_ses.settings().lazy_bitfields)
{
num_lazy_pieces = (std::min)(50, num_pieces / 10);
@ -1470,26 +1467,6 @@ namespace libtorrent
lazy_piece = 0;
}
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " ==> BITFIELD ";
std::stringstream bitfield_string;
for (int i = 0; i < (int)get_bitfield().size(); ++i)
{
if (lazy_piece < num_lazy_pieces
&& lazy_pieces[lazy_piece] == i)
{
bitfield_string << "0";
++lazy_piece;
continue;
}
if (bits[i]) bitfield_string << "1";
else bitfield_string << "0";
}
bitfield_string << "\n";
(*m_logger) << bitfield_string.str();
lazy_piece = 0;
#endif
const int packet_size = (num_pieces + 7) / 8 + 5;
buffer::interval i = allocate_send_buffer(packet_size);
@ -1498,15 +1475,46 @@ namespace libtorrent
detail::write_int32(packet_size - 4, i.begin);
detail::write_uint8(msg_bitfield, i.begin);
memcpy(i.begin, bits.bytes(), packet_size - 5);
if (t->is_seed())
{
memset(i.begin, 0xff, packet_size - 5);
}
else
{
memset(i.begin, 0, packet_size - 5);
piece_picker const& p = t->picker();
int mask = 0x80;
unsigned char* byte = (unsigned char*)i.begin;
for (int i = 0; i < num_pieces; ++i)
{
if (p.have_piece(i)) *byte |= mask;
mask >>= 1;
if (mask == 0)
{
mask = 0x80;
++byte;
}
}
}
for (int c = 0; c < num_lazy_pieces; ++c)
i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7));
TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " ==> BITFIELD ";
std::stringstream bitfield_string;
for (int k = 0; k < num_pieces; ++k)
{
if (i.begin[k / 8] & (0x80 >> (k % 8))) bitfield_string << "1";
else bitfield_string << "0";
}
bitfield_string << "\n";
(*m_logger) << bitfield_string.str();
#endif
#ifndef NDEBUG
m_sent_bitfield = true;
#endif
setup_send();
if (num_lazy_pieces > 0)
{
@ -1522,6 +1530,7 @@ namespace libtorrent
if (m_supports_fast)
send_allowed_set();
setup_send();
}
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -2377,7 +2386,7 @@ namespace libtorrent
// sent the handshake
if (!is_local()) write_handshake();
// if (t->valid_metadata())
// write_bitfield(t->pieces());
// write_bitfield();
if (is_disconnecting()) return;
@ -2511,7 +2520,7 @@ namespace libtorrent
reset_recv_buffer(5);
if (t->valid_metadata())
{
write_bitfield(t->pieces());
write_bitfield();
#ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port);

View File

@ -301,8 +301,11 @@ void http_connection::connect(int ticket, tcp::endpoint target_address)
void http_connection::on_connect(error_code const& e)
{
TORRENT_ASSERT(m_connection_ticket >= 0);
m_cc.done(m_connection_ticket);
if (m_connection_ticket >= 0)
{
m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
}
m_last_receive = time_now();
if (!e)

View File

@ -63,9 +63,10 @@ namespace libtorrent
{
TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left());
boost::tuple<int, int> ret(0, 0);
int start_pos = m_recv_buffer.left();
// early exit if there's nothing new in the receive buffer
if (recv_buffer.left() == m_recv_buffer.left()) return ret;
if (start_pos == recv_buffer.left()) return ret;
m_recv_buffer = recv_buffer;
if (m_state == error_state)
@ -80,7 +81,11 @@ namespace libtorrent
TORRENT_ASSERT(!m_finished);
char const* newline = std::find(pos, recv_buffer.end, '\n');
// if we don't have a full line yet, wait.
if (newline == recv_buffer.end) return ret;
if (newline == recv_buffer.end)
{
boost::get<1>(ret) += m_recv_buffer.left() - start_pos;
return ret;
}
if (newline == pos)
{
@ -96,7 +101,7 @@ namespace libtorrent
++newline;
int incoming = (int)std::distance(pos, newline);
m_recv_pos += incoming;
boost::get<1>(ret) += incoming;
boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
pos = newline;
line >> m_protocol;
@ -114,6 +119,7 @@ namespace libtorrent
m_status_code = 0;
}
m_state = read_header;
start_pos = pos - recv_buffer.begin;
}
if (m_state == read_header)
@ -131,7 +137,6 @@ namespace libtorrent
line.assign(pos, line_end);
++newline;
m_recv_pos += newline - pos;
boost::get<1>(ret) += newline - pos;
pos = newline;
std::string::size_type separator = line.find(':');
@ -187,6 +192,7 @@ namespace libtorrent
TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left());
newline = std::find(pos, recv_buffer.end, '\n');
}
boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
}
if (m_state == read_body)

View File

@ -225,7 +225,14 @@ namespace libtorrent
}
// handle tracker response
entry e = bdecode(data, data + size);
entry e;
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
e = bdecode(data, data + size);
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception&) {}
#endif
if (e.type() != entry::undefined_t)
{

View File

@ -326,15 +326,19 @@ namespace libtorrent
TORRENT_ASSERT(t);
bool interested = false;
bitfield const& we_have = t->pieces();
for (int j = 0; j != (int)we_have.size(); ++j)
if (!t->is_finished())
{
if (!we_have[j]
&& t->piece_priority(j) > 0
&& m_have_piece[j])
piece_picker const& p = t->picker();
int num_pieces = p.num_pieces();
for (int j = 0; j != num_pieces; ++j)
{
interested = true;
break;
if (!p.have_piece(j)
&& t->piece_priority(j) > 0
&& m_have_piece[j])
{
interested = true;
break;
}
}
}
try
@ -2218,6 +2222,10 @@ namespace libtorrent
if (t)
{
// make sure we keep all the stats!
calc_ip_overhead();
t->add_stats(statistics());
if (t->has_picker())
{
piece_picker& picker = t->picker();

View File

@ -58,10 +58,9 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks)
piece_picker::piece_picker()
: m_seeds(0)
, m_priority_boundries(1, int(m_pieces.size()))
, m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece)
, m_num_filtered(0)
, m_num_have_filtered(0)
, m_num_have(0)
@ -69,13 +68,22 @@ namespace libtorrent
, m_dirty(false)
{
#ifdef TORRENT_PICKER_LOG
std::cout << "new piece_picker" << std::endl;
std::cerr << "new piece_picker" << std::endl;
#endif
#ifndef NDEBUG
check_invariant();
#endif
}
void piece_picker::init(int blocks_per_piece, int total_num_blocks)
{
TORRENT_ASSERT(blocks_per_piece > 0);
TORRENT_ASSERT(total_num_blocks >= 0);
#ifndef NDEBUG
m_files_checked_called = false;
#endif
// allocate the piece_map to cover all pieces
// and make them invalid (as if we don't have a single piece)
m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece
, piece_pos(0, 0));
// the piece index is stored in 20 bits, which limits the allowed
// number of pieces somewhat
@ -87,15 +95,6 @@ namespace libtorrent
if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece;
TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece);
// allocate the piece_map to cover all pieces
// and make them invalid (as if we don't have a single piece)
std::fill(m_piece_map.begin(), m_piece_map.end()
, piece_pos(0, 0));
m_num_have = 0;
#ifndef NDEBUG
check_invariant();
#endif
}
void piece_picker::sequential_download(bool sd)
@ -122,24 +121,6 @@ namespace libtorrent
}
}
// pieces is a bitmask with the pieces we have
void piece_picker::init(bitfield const& pieces)
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
#ifndef NDEBUG
m_files_checked_called = true;
#endif
int index = 0;
for (bitfield::const_iterator i = pieces.begin();
i != pieces.end(); ++i, ++index)
{
TORRENT_ASSERT(index < pieces.size());
piece_pos& p = m_piece_map[index];
if (*i) we_have(index);
else TORRENT_ASSERT(p.index == 0);
}
}
void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
@ -249,7 +230,7 @@ namespace libtorrent
for (std::vector<int>::const_iterator i = m_priority_boundries.begin()
, end(m_priority_boundries.end()); i != end; ++i)
{
std::cout << *i << " ";
std::cerr << *i << " ";
}
std::cout << std::endl;
int index = 0;
@ -260,12 +241,12 @@ namespace libtorrent
if (*i == -1) break;
while (j != m_priority_boundries.end() && *j <= index)
{
std::cout << "| ";
std::cerr << "| ";
++j;
}
std::cout << *i << "(" << m_piece_map[*i].index << ") ";
std::cerr << *i << "(" << m_piece_map[*i].index << ") ";
}
std::cout << std::endl;
std::cerr << std::endl;
}
void piece_picker::check_invariant(const torrent* t) const
@ -534,7 +515,7 @@ namespace libtorrent
else new_index = rand() % (range_end - range_start) + range_start;
#ifdef TORRENT_PICKER_LOG
std::cout << "add " << index << " (" << priority << ")" << std::endl;
std::cerr << "add " << index << " (" << priority << ")" << std::endl;
print_pieces();
#endif
m_pieces.push_back(-1);
@ -554,7 +535,7 @@ namespace libtorrent
new_index = temp;
#ifdef TORRENT_PICKER_LOG
print_pieces();
std::cout << " index: " << index
std::cerr << " index: " << index
<< " prio: " << priority
<< " new_index: " << new_index
<< std::endl;
@ -581,7 +562,7 @@ namespace libtorrent
TORRENT_ASSERT(m_sequential_download == -1);
#ifdef TORRENT_PICKER_LOG
std::cout << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl;
std::cerr << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl;
#endif
int next_index = elem_index;
TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == -1);
@ -624,7 +605,6 @@ namespace libtorrent
TORRENT_ASSERT(!m_dirty);
TORRENT_ASSERT(priority >= 0);
TORRENT_ASSERT(elem_index >= 0);
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(m_sequential_download == -1);
TORRENT_ASSERT(int(m_priority_boundries.size()) > priority);
@ -648,7 +628,7 @@ namespace libtorrent
m_priority_boundries.resize(new_priority + 1, m_pieces.size());
#ifdef TORRENT_PICKER_LOG
std::cout << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl;
std::cerr << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl;
#endif
if (priority > new_priority)
{
@ -772,7 +752,6 @@ namespace libtorrent
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(m_piece_map[index].downloading == 1);
@ -804,7 +783,6 @@ namespace libtorrent
void piece_picker::inc_refcount_all()
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(m_files_checked_called);
++m_seeds;
if (m_sequential_download >= 0) return;
if (m_seeds == 1)
@ -819,7 +797,6 @@ namespace libtorrent
void piece_picker::dec_refcount_all()
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(m_files_checked_called);
if (m_sequential_download >= 0)
{
@ -935,7 +912,7 @@ namespace libtorrent
TORRENT_ASSERT(m_sequential_download == -1);
if (m_priority_boundries.empty()) m_priority_boundries.resize(1, 0);
#ifdef TORRENT_PICKER_LOG
std::cout << "update_pieces" << std::endl;
std::cerr << "update_pieces" << std::endl;
#endif
std::fill(m_priority_boundries.begin(), m_priority_boundries.end(), 0);
for (std::vector<piece_pos>::iterator i = m_piece_map.begin()
@ -1004,6 +981,33 @@ namespace libtorrent
#endif
}
void piece_picker::we_dont_have(int index)
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
piece_pos& p = m_piece_map[index];
TORRENT_ASSERT(p.downloading == 0);
if (!p.have()) return;
if (m_sequential_download > index)
m_sequential_download = index;
if (p.filtered())
{
++m_num_filtered;
--m_num_have_filtered;
}
--m_num_have;
p.set_not_have();
if (m_dirty) return;
if (!p.filtered()) add(index);
}
// this is used to indicate that we succesfully have
// downloaded a piece, and that no further attempts
// to pick that piece should be made. The piece will
@ -1167,7 +1171,6 @@ namespace libtorrent
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(num_blocks > 0);
TORRENT_ASSERT(pieces.size() == m_piece_map.size());
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(!m_priority_boundries.empty()
|| m_sequential_download >= 0

View File

@ -200,7 +200,7 @@ namespace libtorrent
int prefer_whole_pieces = c.prefer_whole_pieces();
bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold;
bool rarest_first = t.num_have() >= t.settings().initial_picker_threshold;
if (prefer_whole_pieces == 0)
{
@ -644,7 +644,7 @@ namespace libtorrent
error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
if (m_peers.size() >= m_torrent->settings().max_peerlist_size)
if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size)
{
c.disconnect("peer list size exceeded, refusing incoming connection");
return false;
@ -773,7 +773,7 @@ namespace libtorrent
return 0;
}
if (m_peers.size() >= m_torrent->settings().max_peerlist_size)
if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size)
return 0;
// we don't have any info about this peer.
@ -1018,11 +1018,14 @@ namespace libtorrent
TORRENT_ASSERT(!p->second.connection);
TORRENT_ASSERT(p->second.type == peer::connectable);
TORRENT_ASSERT(is_connect_candidate(p->second, m_torrent->is_finished()));
if (!m_torrent->connect_to_peer(&p->second))
{
++p->second.failcount;
return false;
}
TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished()));
--m_num_connect_candidates;
return true;
}

View File

@ -95,9 +95,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/mount.h>
#endif
#if defined(_WIN32) && defined(UNICODE)
#if TORRENT_USE_WPATH
#ifdef BOOST_WINDOWS
#include <windows.h>
#endif
#include <boost/filesystem/exception.hpp>
#include "libtorrent/utf8.hpp"
#include "libtorrent/buffer.hpp"
@ -249,7 +252,53 @@ namespace
namespace libtorrent
{
template <class Path>
void recursive_copy(Path const& old_path, Path const& new_path, std::string& error)
{
using boost::filesystem::directory_iterator;
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
TORRENT_ASSERT(error.empty());
if (is_directory(old_path))
{
create_directory(new_path);
for (directory_iterator i(old_path), end; i != end; ++i)
{
recursive_copy(i->path(), new_path / i->leaf(), error);
if (!error.empty()) return;
}
}
else
{
copy_file(old_path, new_path);
}
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception& e) { error = e.what(); }
#endif
}
template <class Path>
void recursive_remove(Path const& old_path)
{
using boost::filesystem::directory_iterator;
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
if (is_directory(old_path))
{
for (directory_iterator i(old_path), end; i != end; ++i)
recursive_remove(i->path());
remove(old_path);
}
else
{
remove(old_path);
}
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception& e) {}
#endif
}
std::vector<std::pair<size_type, std::time_t> > get_filesizes(
file_storage const& s, fs::path p)
{
@ -260,7 +309,7 @@ namespace libtorrent
{
size_type size = 0;
std::time_t time = 0;
#if defined(_WIN32) && defined(UNICODE)
#if TORRENT_USE_WPATH
fs::wpath f = safe_convert((p / i->path).string());
#else
fs::path f = p / i->path;
@ -310,7 +359,7 @@ namespace libtorrent
size_type size = 0;
std::time_t time = 0;
#if defined(_WIN32) && defined(UNICODE)
#if TORRENT_USE_WPATH
fs::wpath f = safe_convert((p / i->path).string());
#else
fs::path f = p / i->path;
@ -443,7 +492,7 @@ namespace libtorrent
last_path = dir;
if (!exists_win(last_path))
create_directories_win(last_path);
#elif defined(_WIN32) && defined(UNICODE)
#elif TORRENT_USE_WPATH
last_path = dir;
fs::wpath wp = safe_convert(last_path.string());
if (!exists(wp))
@ -506,9 +555,9 @@ namespace libtorrent
fs::path old_name = m_save_path / files().at(index).path;
m_pool.release(old_name);
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400
fs::wpath old_path = safe_convert(old_name);
fs::wpath new_path = safe_convert(m_save_path / new_filename);
#if TORRENT_USE_WPATH
fs::wpath old_path = safe_convert(old_name.string());
fs::wpath new_path = safe_convert((m_save_path / new_filename).string());
#else
fs::path const& old_path = old_name;
fs::path new_path = m_save_path / new_filename;
@ -565,7 +614,7 @@ namespace libtorrent
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
bp = bp.branch_path();
}
#if defined(_WIN32) && defined(UNICODE)
#if TORRENT_USE_WPATH
try
{ fs::remove(safe_convert(p)); }
catch (std::exception& e)
@ -590,7 +639,7 @@ namespace libtorrent
for (std::set<std::string>::reverse_iterator i = directories.rbegin()
, end(directories.rend()); i != end; ++i)
{
#if defined(_WIN32) && defined(UNICODE)
#if TORRENT_USE_WPATH
try
{ fs::remove(safe_convert(*i)); }
catch (std::exception& e)
@ -725,7 +774,7 @@ namespace libtorrent
// returns true on success
bool storage::move_storage(fs::path save_path)
{
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400
#if TORRENT_USE_WPATH
fs::wpath old_path;
fs::wpath new_path;
#else
@ -741,7 +790,7 @@ namespace libtorrent
CreateDirectory(wsave_path.c_str(), 0);
else if ((GetFileAttributes(wsave_path.c_str()) & FILE_ATTRIBUTE_DIRECTORY) == 0)
return false;
#elif defined(_WIN32) && defined(UNICODE)
#elif TORRENT_USE_WPATH
fs::wpath wp = safe_convert(save_path.string());
if (!exists(wp))
create_directory(wp);
@ -756,7 +805,7 @@ namespace libtorrent
m_pool.release(this);
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400
#if TORRENT_USE_WPATH
old_path = safe_convert((m_save_path / files().name()).string());
new_path = safe_convert((save_path / files().name()).string());
#else
@ -770,7 +819,6 @@ namespace libtorrent
#endif
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
rename_win(old_path, new_path);
rename(old_path, new_path);
#else
rename(old_path, new_path);
#endif
@ -780,8 +828,15 @@ namespace libtorrent
}
catch (std::exception& e)
{
set_error((m_save_path / files().name()).string(), e.what());
return true;
std::string err;
recursive_copy(old_path, new_path, err);
if (!err.empty())
{
set_error((m_save_path / files().name()).string(), e.what());
return true;
}
m_save_path = save_path;
recursive_remove(old_path);
}
#endif
return false;
@ -1648,7 +1703,7 @@ namespace libtorrent
#endif
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
file_exists = exists_win(f);
#elif defined(_WIN32) && defined(UNICODE)
#elif TORRENT_USE_WPATH
fs::wpath wf = safe_convert(f.string());
file_exists = exists(wf);
#else

View File

@ -164,7 +164,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15))
#endif
, m_ses(ses)
, m_picker(0)
, m_picker(new piece_picker())
, m_trackers(m_torrent_file->trackers())
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
@ -175,7 +175,6 @@ namespace libtorrent
, m_settings(ses.settings())
, m_storage_constructor(sc)
, m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0)
@ -201,11 +200,10 @@ namespace libtorrent
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_connections_initialized(true)
, m_has_incoming(false)
, m_files_checked(false)
{
if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG
m_files_checked = false;
#endif
}
torrent::torrent(
@ -239,7 +237,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15))
#endif
, m_ses(ses)
, m_picker(0)
, m_picker(new piece_picker())
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
, m_net_interface(net_interface.address(), 0)
@ -249,7 +247,6 @@ namespace libtorrent
, m_settings(ses.settings())
, m_storage_constructor(sc)
, m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0)
@ -275,6 +272,7 @@ namespace libtorrent
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_connections_initialized(false)
, m_has_incoming(false)
{
if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG
@ -308,10 +306,10 @@ namespace libtorrent
if (m_ses.m_listen_sockets.empty()) return false;
if (!m_ses.m_dht) return false;
if (!m_files_checked) return false;
// don't announce private torrents
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
if (m_trackers.empty()) return true;
return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback;
@ -407,16 +405,14 @@ namespace libtorrent
TORRENT_ASSERT(m_torrent_file->num_files() > 0);
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
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_mode);
m_storage = m_owning_storage.get();
m_picker.reset(new piece_picker(
m_torrent_file->piece_length() / m_block_size
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
m_picker->init(m_torrent_file->piece_length() / m_block_size
, 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::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
@ -473,8 +469,6 @@ namespace libtorrent
" ]\n";
#endif
}
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str;
pause();
return;
@ -548,8 +542,6 @@ namespace libtorrent
// there are either no files for this torrent
// or the resume_data was accepted
m_num_pieces = 0;
m_have_pieces.clear_all();
if (!fastresume_rejected)
{
TORRENT_ASSERT(m_resume_data.type() == entry::dictionary_t);
@ -563,8 +555,7 @@ namespace libtorrent
for (int i = 0, end(pieces_str.size()); i < end; ++i)
{
if ((pieces_str[i] & 1) == 0) continue;
m_have_pieces.set_bit(i);
++m_num_pieces;
m_picker->we_have(i);
}
}
@ -587,11 +578,8 @@ namespace libtorrent
if (piece_index < 0 || piece_index >= torrent_file().num_pieces())
continue;
if (m_have_pieces[piece_index])
{
m_have_pieces.clear_bit(piece_index);
--m_num_pieces;
}
if (m_picker->have_piece(piece_index))
m_picker->we_dont_have(piece_index);
entry const* bitmask_ent = i->find_key("bitmask");
if (bitmask_ent == 0 || bitmask_ent->type() != entry::string_t) break;
@ -617,13 +605,6 @@ namespace libtorrent
}
}
}
int index = 0;
for (bitfield::const_iterator i = m_have_pieces.begin()
, end(m_have_pieces.end()); i != end; ++i, ++index)
{
if (*i) m_picker->we_have(index);
}
}
files_checked();
@ -636,6 +617,51 @@ namespace libtorrent
}
}
void torrent::force_recheck()
{
disconnect_all();
m_owning_storage->async_release_files();
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
, m_storage_mode);
m_storage = m_owning_storage.get();
m_picker.reset(new piece_picker);
m_picker->init(m_torrent_file->piece_length() / m_block_size
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
// assume that we don't have anything
m_files_checked = false;
m_state = torrent_status::queued_for_checking;
m_resume_data = entry();
m_storage->async_check_fastresume(&m_resume_data
, bind(&torrent::on_force_recheck
, shared_from_this(), _1, _2));
}
void torrent::on_force_recheck(int ret, disk_io_job const& j)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
if (ret == piece_manager::fatal_disk_error)
{
if (m_ses.m_alerts.should_post(alert::fatal))
{
m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
" error: " << j.str <<
" torrent: " << torrent_file().name() <<
" ]\n";
#endif
}
m_error = j.str;
pause();
return;
}
m_ses.check_torrent(shared_from_this());
}
void torrent::start_checking()
{
m_state = torrent_status::checking_files;
@ -661,8 +687,6 @@ namespace libtorrent
" ]\n";
#endif
}
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str;
pause();
m_ses.done_checking(shared_from_this());
@ -671,13 +695,9 @@ namespace libtorrent
m_progress = j.piece / float(torrent_file().num_pieces());
if (j.offset >= 0 && !m_have_pieces[j.offset])
{
m_have_pieces.set_bit(j.offset);
++m_num_pieces;
TORRENT_ASSERT(m_picker);
TORRENT_ASSERT(m_picker);
if (j.offset >= 0 && !m_picker->have_piece(j.offset))
m_picker->we_have(j.offset);
}
// we're not done checking yet
// this handler will be called repeatedly until
@ -793,6 +813,7 @@ namespace libtorrent
// INVARIANT_CHECK;
if (m_trackers.empty()) return false;
if (!m_files_checked) return false;
if (m_just_paused)
{
@ -982,12 +1003,12 @@ namespace libtorrent
const int last_piece = m_torrent_file->num_pieces() - 1;
size_type total_done
= size_type(m_num_pieces) * m_torrent_file->piece_length();
= size_type(num_have()) * 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])
if (m_picker->have_piece(last_piece))
{
int corr = m_torrent_file->piece_size(last_piece)
- m_torrent_file->piece_length();
@ -1013,19 +1034,19 @@ namespace libtorrent
return make_tuple(m_torrent_file->total_size()
, m_torrent_file->total_size());
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered());
size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered())
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered())
* piece_size;
TORRENT_ASSERT(wanted_done >= 0);
size_type total_done
= size_type(m_num_pieces) * piece_size;
TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces());
= size_type(num_have()) * piece_size;
TORRENT_ASSERT(num_have() < 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])
if (m_picker->have_piece(last_piece))
{
TORRENT_ASSERT(total_done >= piece_size);
int corr = m_torrent_file->piece_size(last_piece)
@ -1054,7 +1075,7 @@ namespace libtorrent
{
int corr = 0;
int index = i->index;
if (m_have_pieces[index]) continue;
if (m_picker->have_piece(index)) continue;
TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index));
#ifndef NDEBUG
@ -1099,7 +1120,7 @@ namespace libtorrent
= pc->downloading_piece_progress();
if (p)
{
if (m_have_pieces[p->piece_index])
if (m_picker->have_piece(p->piece_index))
continue;
piece_block block(p->piece_index, p->block_index);
@ -1136,16 +1157,16 @@ namespace libtorrent
wanted_done += i->second;
}
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
#ifndef NDEBUG
if (total_done >= m_torrent_file->total_size())
{
// Thist happens when a piece has been downloaded completely
// but not yet verified against the hash
std::copy(m_have_pieces.begin(), m_have_pieces.end()
, std::ostream_iterator<bool>(std::cerr, " "));
std::cerr << std::endl;
std::cerr << "num_pieces: " << m_num_pieces << std::endl;
std::cerr << "num_have: " << num_have() << std::endl;
std::cerr << "unfinished:" << std::endl;
@ -1195,7 +1216,7 @@ namespace libtorrent
?"disk failed":"failed") << " ]\n";
#endif
bool was_finished = m_picker->num_filtered() + num_pieces()
bool was_finished = m_picker->num_filtered() + num_have()
== torrent_file().num_pieces();
if (passed_hash_check == 0)
@ -1226,7 +1247,7 @@ namespace libtorrent
if (!was_finished
&& (is_seed()
|| m_picker->num_filtered() + num_pieces()
|| m_picker->num_filtered() + num_have()
== torrent_file().num_pieces()))
{
TORRENT_ASSERT(passed_hash_check == 0);
@ -1350,7 +1371,7 @@ namespace libtorrent
m_picker->restore_piece(index);
TORRENT_ASSERT(m_storage);
TORRENT_ASSERT(m_have_pieces[index] == false);
TORRENT_ASSERT(m_picker->have_piece(index) == false);
#ifndef NDEBUG
for (std::vector<void*>::iterator i = downloaders.begin()
@ -1486,13 +1507,6 @@ namespace libtorrent
std::set<void*> peers;
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
if (!m_have_pieces[index])
m_num_pieces++;
m_have_pieces.set_bit(index);
TORRENT_ASSERT(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0)
== m_num_pieces);
m_picker->we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index);
@ -1558,7 +1572,7 @@ namespace libtorrent
bool was_finished = is_finished();
bool filter_updated = m_picker->set_piece_priority(index, priority);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered());
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
if (filter_updated) update_peer_interest(was_finished);
}
@ -1596,7 +1610,7 @@ namespace libtorrent
TORRENT_ASSERT(*i >= 0);
TORRENT_ASSERT(*i <= 7);
filter_updated |= m_picker->set_piece_priority(index, *i);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered());
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
}
if (filter_updated) update_peer_interest(was_finished);
}
@ -2442,8 +2456,16 @@ namespace libtorrent
// write have bitmask
entry::string_type& pieces = ret["pieces"].string();
pieces.resize(m_torrent_file->num_pieces());
for (int i = 0, end(pieces.size()); i < end; ++i)
pieces[i] = m_have_pieces[i] ? 1 : 0;
if (is_seed())
{
for (int i = 0, end(pieces.size()); i < end; ++i)
pieces[i] = 1;
}
else
{
for (int i = 0, end(pieces.size()); i < end; ++i)
pieces[i] = m_picker->have_piece(i) ? 1 : 0;
}
// write local peers
@ -2714,6 +2736,8 @@ namespace libtorrent
TORRENT_ASSERT(p != 0);
TORRENT_ASSERT(!p->is_local());
m_has_incoming = true;
if ((m_state == torrent_status::queued_for_checking
|| m_state == torrent_status::checking_files)
&& valid_metadata())
@ -3115,7 +3139,6 @@ namespace libtorrent
if (!is_seed())
{
m_picker->init(m_have_pieces);
if (m_sequential_download)
picker().sequential_download(m_sequential_download);
}
@ -3169,9 +3192,7 @@ namespace libtorrent
, "torrent finished checking"));
}
#ifndef NDEBUG
m_files_checked = true;
#endif
}
alert_manager& torrent::alerts() const
@ -3289,16 +3310,16 @@ namespace libtorrent
if (!m_picker->is_downloaded(i->first))
TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
}
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered());
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
}
if (valid_metadata())
{
TORRENT_ASSERT(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces());
TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces());
}
else
{
TORRENT_ASSERT(m_abort || m_have_pieces.empty());
TORRENT_ASSERT(m_abort || m_picker->num_pieces() == 0);
}
for (policy::const_iterator i = m_policy.begin_peer()
@ -3313,7 +3334,7 @@ namespace libtorrent
if (is_seed())
TORRENT_ASSERT(total_done == m_torrent_file->total_size());
else
TORRENT_ASSERT(total_done != m_torrent_file->total_size());
TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked);
}
else
{
@ -3344,8 +3365,6 @@ namespace libtorrent
}
// This check is very expensive.
TORRENT_ASSERT(m_num_pieces
== std::count(m_have_pieces.begin(), m_have_pieces.end(), true));
TORRENT_ASSERT(!valid_metadata() || m_block_size > 0);
TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
@ -3412,6 +3431,9 @@ namespace libtorrent
}
m_sequence_number = (std::min)(max_seq + 1, p);
}
if (m_ses.m_auto_manage_time_scaler > 2)
m_ses.m_auto_manage_time_scaler = 2;
}
void torrent::set_max_uploads(int limit)
@ -3814,7 +3836,7 @@ namespace libtorrent
TORRENT_ASSERT(m_storage->refcount() > 0);
TORRENT_ASSERT(piece_index >= 0);
TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces());
TORRENT_ASSERT(piece_index < (int)m_have_pieces.size());
TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces());
#ifndef NDEBUG
if (m_picker)
{
@ -3865,6 +3887,12 @@ namespace libtorrent
TORRENT_ASSERT(valid_metadata());
fp.clear();
if (is_seed())
{
fp.resize(m_torrent_file->num_files(), 1.f);
return;
}
fp.resize(m_torrent_file->num_files(), 0.f);
for (int i = 0; i < m_torrent_file->num_files(); ++i)
@ -3885,7 +3913,7 @@ namespace libtorrent
{
size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece)
- ret.start), size);
if (m_have_pieces[ret.piece]) done += bytes_step;
if (m_picker->have_piece(ret.piece)) done += bytes_step;
++ret.piece;
ret.start = 0;
size -= bytes_step;
@ -3900,15 +3928,11 @@ namespace libtorrent
{
INVARIANT_CHECK;
TORRENT_ASSERT(std::accumulate(
m_have_pieces.begin()
, m_have_pieces.end()
, 0) == m_num_pieces);
ptime now = time_now();
torrent_status st;
st.has_incoming = m_has_incoming;
st.error = m_error;
if (m_last_scrape == min_time())
@ -4030,8 +4054,14 @@ namespace libtorrent
else st.progress = st.total_wanted_done
/ static_cast<float>(st.total_wanted);
st.pieces = &m_have_pieces;
st.num_pieces = m_num_pieces;
if (has_picker())
{
int num_pieces = m_picker->num_pieces();
st.pieces.resize(num_pieces, false);
for (int i = 0; i < num_pieces; ++i)
if (m_picker->have_piece(i)) st.pieces.set_bit(i);
}
st.num_pieces = num_have();
st.num_seeds = num_seeds();
if (m_picker.get())
st.distributed_copies = m_picker->distributed_copies();

View File

@ -265,6 +265,12 @@ namespace libtorrent
TORRENT_FORWARD(save_resume_data());
}
void torrent_handle::force_recheck() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(force_recheck());
}
void torrent_handle::resume() const
{
INVARIANT_CHECK;

View File

@ -67,6 +67,7 @@ namespace libtorrent
: peer_connection(ses, t, s, remote, peerinfo)
, m_url(url)
, m_first_request(true)
, m_range_pos(0)
{
INVARIANT_CHECK;
@ -350,7 +351,8 @@ namespace libtorrent
{
bool error = false;
boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error);
m_statistics.received_bytes(payload, protocol);
m_statistics.received_bytes(0, protocol);
bytes_transferred -= protocol;
if (error)
{
@ -363,7 +365,12 @@ namespace libtorrent
TORRENT_ASSERT(recv_buffer.left() <= packet_size());
// this means the entire status line hasn't been received yet
if (m_parser.status_code() == -1) break;
if (m_parser.status_code() == -1)
{
TORRENT_ASSERT(payload == 0);
TORRENT_ASSERT(bytes_transferred == 0);
break;
}
// if the status code is not one of the accepted ones, abort
if (m_parser.status_code() != 206 // partial content
@ -388,15 +395,16 @@ namespace libtorrent
disconnect(error_msg.c_str(), 1);
return;
}
if (!m_parser.header_finished()) break;
if (!m_parser.header_finished())
{
TORRENT_ASSERT(payload == 0);
TORRENT_ASSERT(bytes_transferred == 0);
break;
}
m_body_start = m_parser.body_start();
m_received_body = 0;
}
else
{
m_statistics.received_bytes(bytes_transferred, 0);
}
// we just completed reading the header
if (!header_finished)
@ -460,9 +468,11 @@ namespace libtorrent
m_body_start = m_parser.body_start();
m_received_body = 0;
m_range_pos = 0;
}
recv_buffer.begin += m_body_start;
// we only received the header, no data
if (recv_buffer.left() == 0) break;
@ -499,6 +509,13 @@ namespace libtorrent
}
}
int left_in_response = range_end - range_start - m_range_pos;
int payload_transferred = (std::min)(left_in_response, int(bytes_transferred));
m_statistics.received_bytes(payload_transferred, 0);
bytes_transferred -= payload_transferred;
m_range_pos += payload_transferred;;
if (m_range_pos > range_end - range_start) m_range_pos = range_end - range_start;
// std::cerr << "REQUESTS: m_requests: " << m_requests.size()
// << " file_requests: " << m_file_requests.size() << std::endl;
@ -641,8 +658,9 @@ namespace libtorrent
m_received_body = 0;
continue;
}
break;
if (bytes_transferred == 0) break;
}
TORRENT_ASSERT(bytes_transferred == 0);
}
void web_peer_connection::get_specific_peer_info(peer_info& p) const