replaced vector<bool> with a custom bitfield type
This commit is contained in:
parent
523c48e069
commit
68c31e48dc
|
@ -195,7 +195,7 @@ peer_plugin
|
||||||
virtual bool on_interested();
|
virtual bool on_interested();
|
||||||
virtual bool on_not_interested();
|
virtual bool on_not_interested();
|
||||||
virtual bool on_have(int index);
|
virtual bool on_have(int index);
|
||||||
virtual bool on_bitfield(std::vector<bool> const& bitfield);
|
virtual bool on_bitfield(bitfield const& bits);
|
||||||
virtual bool on_have_all();
|
virtual bool on_have_all();
|
||||||
virtual bool on_have_none();
|
virtual bool on_have_none();
|
||||||
virtual bool on_allowed_fast(int index);
|
virtual bool on_allowed_fast(int index);
|
||||||
|
|
|
@ -5,6 +5,7 @@ libtorrent/bandwidth_manager.hpp \
|
||||||
libtorrent/bandwidth_limit.hpp \
|
libtorrent/bandwidth_limit.hpp \
|
||||||
libtorrent/bandwidth_queue_entry.hpp \
|
libtorrent/bandwidth_queue_entry.hpp \
|
||||||
libtorrent/bencode.hpp \
|
libtorrent/bencode.hpp \
|
||||||
|
libtorrent/bitfield.hpp \
|
||||||
libtorrent/broadcast_socket.hpp \
|
libtorrent/broadcast_socket.hpp \
|
||||||
libtorrent/buffer.hpp \
|
libtorrent/buffer.hpp \
|
||||||
libtorrent/connection_queue.hpp \
|
libtorrent/connection_queue.hpp \
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2008, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TORRENT_BITFIELD_HPP_INCLUDED
|
||||||
|
#define TORRENT_BITFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "libtorrent/assert.hpp"
|
||||||
|
#include "libtorrent/config.hpp"
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
struct TORRENT_EXPORT bitfield
|
||||||
|
{
|
||||||
|
bitfield(): m_bytes(0), m_size(0), m_own(false) {}
|
||||||
|
bitfield(int bits): m_bytes(0), m_size(0)
|
||||||
|
{ resize(bits); }
|
||||||
|
bitfield(int bits, bool val): m_bytes(0), m_size(0)
|
||||||
|
{ resize(bits, val); }
|
||||||
|
bitfield(char const* bytes, int bits): m_bytes(0), m_size(0)
|
||||||
|
{ assign(bytes, bits); }
|
||||||
|
bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
|
||||||
|
{ assign(rhs.bytes(), rhs.size()); }
|
||||||
|
|
||||||
|
void borrow_bytes(char* bytes, int bits)
|
||||||
|
{
|
||||||
|
dealloc();
|
||||||
|
m_bytes = (unsigned char*)bytes;
|
||||||
|
m_size = bits;
|
||||||
|
m_own = false;
|
||||||
|
}
|
||||||
|
~bitfield() { dealloc(); }
|
||||||
|
|
||||||
|
void assign(char const* bytes, int bits)
|
||||||
|
{ resize(bits); memcpy(m_bytes, bytes, (bits + 7) / 8); }
|
||||||
|
|
||||||
|
bool operator[](int index) const
|
||||||
|
{ return get_bit(index); }
|
||||||
|
|
||||||
|
bool get_bit(int index) const
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(index >= 0);
|
||||||
|
TORRENT_ASSERT(index < m_size);
|
||||||
|
return m_bytes[index / 8] & (0x80 >> (index & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_bit(int index)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(index >= 0);
|
||||||
|
TORRENT_ASSERT(index < m_size);
|
||||||
|
m_bytes[index / 8] &= ~(0x80 >> (index & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_bit(int index)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(index >= 0);
|
||||||
|
TORRENT_ASSERT(index < m_size);
|
||||||
|
m_bytes[index / 8] |= (0x80 >> (index & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const { return m_size; }
|
||||||
|
bool empty() const { return m_size == 0; }
|
||||||
|
|
||||||
|
char const* bytes() const { return (char*)m_bytes; }
|
||||||
|
|
||||||
|
bitfield& operator=(bitfield const& rhs)
|
||||||
|
{
|
||||||
|
assign(rhs.bytes(), rhs.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count() const
|
||||||
|
{
|
||||||
|
// 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
|
||||||
|
// 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
|
||||||
|
const static char num_bits[] =
|
||||||
|
{
|
||||||
|
0, 1, 1, 2, 1, 2, 2, 3,
|
||||||
|
1, 2, 2, 3, 2, 3, 3, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
const int num_bytes = m_size / 8;
|
||||||
|
for (int i = 0; i < num_bytes; ++i)
|
||||||
|
{
|
||||||
|
ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
int rest = m_size - num_bytes * 8;
|
||||||
|
for (int i = 0; i < rest; ++i)
|
||||||
|
{
|
||||||
|
ret += (m_bytes[num_bytes] >> (7-i)) & 1;
|
||||||
|
}
|
||||||
|
TORRENT_ASSERT(ret <= m_size);
|
||||||
|
TORRENT_ASSERT(ret >= 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct const_iterator
|
||||||
|
{
|
||||||
|
friend struct bitfield;
|
||||||
|
|
||||||
|
typedef bool value_type;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef bool const* pointer;
|
||||||
|
typedef bool& reference;
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
bool operator*() { return *byte & bit; }
|
||||||
|
const_iterator& operator++() { inc(); return *this; }
|
||||||
|
const_iterator operator++(int)
|
||||||
|
{ const_iterator ret(*this); inc(); return ret; }
|
||||||
|
const_iterator& operator--() { dec(); return *this; }
|
||||||
|
const_iterator operator--(int)
|
||||||
|
{ const_iterator ret(*this); dec(); return ret; }
|
||||||
|
|
||||||
|
const_iterator(): byte(0), bit(0x80) {}
|
||||||
|
bool operator==(const_iterator const& rhs) const
|
||||||
|
{ return byte == rhs.byte && bit == rhs.bit; }
|
||||||
|
|
||||||
|
bool operator!=(const_iterator const& rhs) const
|
||||||
|
{ return byte != rhs.byte || bit != rhs.bit; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void inc()
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(byte);
|
||||||
|
if (bit == 0x01)
|
||||||
|
{
|
||||||
|
bit = 0x80;
|
||||||
|
++byte;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void dec()
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(byte);
|
||||||
|
if (bit == 0x80)
|
||||||
|
{
|
||||||
|
bit = 0x01;
|
||||||
|
--byte;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const_iterator(unsigned char const* ptr, int offset)
|
||||||
|
: byte(ptr), bit(0x80 >> offset) {}
|
||||||
|
unsigned char const* byte;
|
||||||
|
int bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
const_iterator begin() const { return const_iterator(m_bytes, 0); }
|
||||||
|
const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); }
|
||||||
|
|
||||||
|
void resize(int bits, bool val)
|
||||||
|
{
|
||||||
|
resize(bits);
|
||||||
|
if (val) set_all(); else clear_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_all()
|
||||||
|
{
|
||||||
|
memset(m_bytes, 0xff, (m_size + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_all()
|
||||||
|
{
|
||||||
|
memset(m_bytes, 0x00, (m_size + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(int bits)
|
||||||
|
{
|
||||||
|
const int bytes = (bits + 7) / 8;
|
||||||
|
if (m_bytes)
|
||||||
|
{
|
||||||
|
if (m_own)
|
||||||
|
{
|
||||||
|
m_bytes = (unsigned char*)realloc(m_bytes, bytes);
|
||||||
|
m_own = true;
|
||||||
|
}
|
||||||
|
else if (bits > m_size)
|
||||||
|
{
|
||||||
|
unsigned char* tmp = (unsigned char*)malloc(bytes);
|
||||||
|
memcpy(tmp, m_bytes, (std::min)((m_size + 7)/ 8, bytes));
|
||||||
|
m_bytes = tmp;
|
||||||
|
m_own = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bytes = (unsigned char*)malloc(bytes);
|
||||||
|
m_own = true;
|
||||||
|
}
|
||||||
|
m_size = bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void dealloc() { if (m_own) free(m_bytes); m_bytes = 0; }
|
||||||
|
unsigned char* m_bytes;
|
||||||
|
int m_size; // in bits
|
||||||
|
bool m_own;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TORRENT_BITFIELD_HPP_INCLUDED
|
||||||
|
|
|
@ -209,7 +209,7 @@ namespace libtorrent
|
||||||
void write_not_interested();
|
void write_not_interested();
|
||||||
void write_request(peer_request const& r);
|
void write_request(peer_request const& r);
|
||||||
void write_cancel(peer_request const& r);
|
void write_cancel(peer_request const& r);
|
||||||
void write_bitfield(std::vector<bool> const& bitfield);
|
void write_bitfield(bitfield const& bits);
|
||||||
void write_have(int index);
|
void write_have(int index);
|
||||||
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
|
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
|
||||||
void write_handshake();
|
void write_handshake();
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace libtorrent
|
||||||
class peer_connection;
|
class peer_connection;
|
||||||
class entry;
|
class entry;
|
||||||
struct disk_buffer_holder;
|
struct disk_buffer_holder;
|
||||||
|
struct bitfield;
|
||||||
|
|
||||||
struct TORRENT_EXPORT torrent_plugin
|
struct TORRENT_EXPORT torrent_plugin
|
||||||
{
|
{
|
||||||
|
@ -129,7 +130,7 @@ namespace libtorrent
|
||||||
virtual bool on_have(int index)
|
virtual bool on_have(int index)
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
|
||||||
virtual bool on_bitfield(std::vector<bool> const& bitfield)
|
virtual bool on_bitfield(bitfield const& bitfield)
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
|
||||||
virtual bool on_have_all()
|
virtual bool on_have_all()
|
||||||
|
|
|
@ -76,6 +76,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
#include "libtorrent/chained_buffer.hpp"
|
#include "libtorrent/chained_buffer.hpp"
|
||||||
#include "libtorrent/disk_buffer_holder.hpp"
|
#include "libtorrent/disk_buffer_holder.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -242,7 +243,7 @@ namespace libtorrent
|
||||||
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
||||||
tcp::endpoint const& remote() const { return m_remote; }
|
tcp::endpoint const& remote() const { return m_remote; }
|
||||||
|
|
||||||
std::vector<bool> const& get_bitfield() const;
|
bitfield const& get_bitfield() const;
|
||||||
std::vector<int> const& allowed_fast();
|
std::vector<int> const& allowed_fast();
|
||||||
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
|
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
|
||||||
|
|
||||||
|
@ -328,7 +329,7 @@ namespace libtorrent
|
||||||
void incoming_interested();
|
void incoming_interested();
|
||||||
void incoming_not_interested();
|
void incoming_not_interested();
|
||||||
void incoming_have(int piece_index);
|
void incoming_have(int piece_index);
|
||||||
void incoming_bitfield(std::vector<bool> const& bitfield);
|
void incoming_bitfield(bitfield const& bits);
|
||||||
void incoming_request(peer_request const& r);
|
void incoming_request(peer_request const& r);
|
||||||
void incoming_piece(peer_request const& p, disk_buffer_holder& data);
|
void incoming_piece(peer_request const& p, disk_buffer_holder& data);
|
||||||
void incoming_piece(peer_request const& p, char const* data);
|
void incoming_piece(peer_request const& p, char const* data);
|
||||||
|
@ -629,7 +630,7 @@ namespace libtorrent
|
||||||
peer_id m_peer_id;
|
peer_id m_peer_id;
|
||||||
|
|
||||||
// the pieces the other end have
|
// the pieces the other end have
|
||||||
std::vector<bool> m_have_piece;
|
bitfield m_have_piece;
|
||||||
|
|
||||||
// the queue of requests we have got
|
// the queue of requests we have got
|
||||||
// from this peer
|
// from this peer
|
||||||
|
|
|
@ -33,12 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
|
#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
|
||||||
#define TORRENT_PEER_INFO_HPP_INCLUDED
|
#define TORRENT_PEER_INFO_HPP_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include "libtorrent/peer_id.hpp"
|
#include "libtorrent/peer_id.hpp"
|
||||||
#include "libtorrent/size_type.hpp"
|
#include "libtorrent/size_type.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -96,7 +95,7 @@ namespace libtorrent
|
||||||
size_type total_download;
|
size_type total_download;
|
||||||
size_type total_upload;
|
size_type total_upload;
|
||||||
peer_id pid;
|
peer_id pid;
|
||||||
std::vector<bool> pieces;
|
bitfield pieces;
|
||||||
int upload_limit;
|
int upload_limit;
|
||||||
int download_limit;
|
int download_limit;
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace libtorrent
|
||||||
|
|
||||||
class torrent;
|
class torrent;
|
||||||
class peer_connection;
|
class peer_connection;
|
||||||
|
class bitfield;
|
||||||
|
|
||||||
struct TORRENT_EXPORT piece_block
|
struct TORRENT_EXPORT piece_block
|
||||||
{
|
{
|
||||||
|
@ -138,7 +139,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// the vector tells which pieces we already have
|
// the vector tells which pieces we already have
|
||||||
// and which we don't have.
|
// and which we don't have.
|
||||||
void init(std::vector<bool> const& pieces);
|
void init(bitfield const& pieces);
|
||||||
|
|
||||||
// increases the peer count for the given piece
|
// increases the peer count for the given piece
|
||||||
// (is used when a HAVE message is received)
|
// (is used when a HAVE message is received)
|
||||||
|
@ -147,10 +148,10 @@ namespace libtorrent
|
||||||
|
|
||||||
// increases the peer count for the given piece
|
// increases the peer count for the given piece
|
||||||
// (is used when a BITFIELD message is received)
|
// (is used when a BITFIELD message is received)
|
||||||
void inc_refcount(std::vector<bool> const& bitmask);
|
void inc_refcount(bitfield const& bitmask);
|
||||||
// decreases the peer count for the given piece
|
// decreases the peer count for the given piece
|
||||||
// (used when a peer disconnects)
|
// (used when a peer disconnects)
|
||||||
void dec_refcount(std::vector<bool> const& bitmask);
|
void dec_refcount(bitfield const& bitmask);
|
||||||
|
|
||||||
// these will increase and decrease the peer count
|
// these will increase and decrease the peer count
|
||||||
// of all pieces. They are used when seeds join
|
// of all pieces. They are used when seeds join
|
||||||
|
@ -193,7 +194,7 @@ namespace libtorrent
|
||||||
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
|
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
|
||||||
// The last argument is the policy::peer pointer for the peer that
|
// The last argument is the policy::peer pointer for the peer that
|
||||||
// we'll download from.
|
// we'll download from.
|
||||||
void pick_pieces(std::vector<bool> const& pieces
|
void pick_pieces(bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, int num_pieces, int prefer_whole_pieces
|
, int num_pieces, int prefer_whole_pieces
|
||||||
, void* peer, piece_state_t speed
|
, void* peer, piece_state_t speed
|
||||||
|
@ -207,14 +208,14 @@ namespace libtorrent
|
||||||
// blocks to be picked. Blocks are not picked from pieces
|
// blocks to be picked. Blocks are not picked from pieces
|
||||||
// that are being downloaded
|
// that are being downloaded
|
||||||
int add_blocks(std::vector<int> const& piece_list
|
int add_blocks(std::vector<int> const& piece_list
|
||||||
, const std::vector<bool>& pieces
|
, bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, int num_blocks, int prefer_whole_pieces
|
, int num_blocks, int prefer_whole_pieces
|
||||||
, void* peer, std::vector<int> const& ignore) const;
|
, void* peer, std::vector<int> const& ignore) const;
|
||||||
|
|
||||||
// picks blocks only from downloading pieces
|
// picks blocks only from downloading pieces
|
||||||
int add_blocks_downloading(
|
int add_blocks_downloading(
|
||||||
std::vector<bool> const& pieces
|
bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, std::vector<piece_block>& backup_blocks
|
, std::vector<piece_block>& backup_blocks
|
||||||
, int num_blocks, int prefer_whole_pieces
|
, int num_blocks, int prefer_whole_pieces
|
||||||
|
@ -280,7 +281,7 @@ namespace libtorrent
|
||||||
void verify_priority(int start, int end, int prio) const;
|
void verify_priority(int start, int end, int prio) const;
|
||||||
void check_invariant(const torrent* t = 0) const;
|
void check_invariant(const torrent* t = 0) const;
|
||||||
void verify_pick(std::vector<piece_block> const& picked
|
void verify_pick(std::vector<piece_block> const& picked
|
||||||
, std::vector<bool> const& bitfield) const;
|
, bitfield const& bits) const;
|
||||||
void print_pieces() const;
|
void print_pieces() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -302,9 +303,9 @@ namespace libtorrent
|
||||||
|
|
||||||
friend struct piece_pos;
|
friend struct piece_pos;
|
||||||
|
|
||||||
bool can_pick(int piece, std::vector<bool> const& bitmask) const;
|
bool can_pick(int piece, bitfield const& bitmask) const;
|
||||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||||
, std::vector<bool> const& have) const;
|
, bitfield const& have) const;
|
||||||
|
|
||||||
struct piece_pos
|
struct piece_pos
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,6 +70,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/storage.hpp"
|
#include "libtorrent/storage.hpp"
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -79,6 +80,7 @@ namespace libtorrent
|
||||||
|
|
||||||
class piece_manager;
|
class piece_manager;
|
||||||
struct torrent_plugin;
|
struct torrent_plugin;
|
||||||
|
struct bitfield;
|
||||||
|
|
||||||
namespace aux
|
namespace aux
|
||||||
{
|
{
|
||||||
|
@ -376,7 +378,7 @@ namespace libtorrent
|
||||||
return m_have_pieces[index];
|
return m_have_pieces[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<bool>& pieces() const
|
bitfield const& pieces() const
|
||||||
{ return m_have_pieces; }
|
{ return m_have_pieces; }
|
||||||
|
|
||||||
int num_pieces() const { return m_num_pieces; }
|
int num_pieces() const { return m_num_pieces; }
|
||||||
|
@ -399,12 +401,12 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// when we get a bitfield message, this is called for that piece
|
// when we get a bitfield message, this is called for that piece
|
||||||
void peer_has(std::vector<bool> const& bitfield)
|
void peer_has(bitfield const& bits)
|
||||||
{
|
{
|
||||||
if (m_picker.get())
|
if (m_picker.get())
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!is_seed());
|
TORRENT_ASSERT(!is_seed());
|
||||||
m_picker->inc_refcount(bitfield);
|
m_picker->inc_refcount(bits);
|
||||||
}
|
}
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
else
|
else
|
||||||
|
@ -729,7 +731,7 @@ namespace libtorrent
|
||||||
// this is an index into m_trackers
|
// this is an index into m_trackers
|
||||||
|
|
||||||
// the bitmask that says which pieces we have
|
// the bitmask that says which pieces we have
|
||||||
std::vector<bool> m_have_pieces;
|
bitfield m_have_pieces;
|
||||||
|
|
||||||
// the number of bytes that has been
|
// the number of bytes that has been
|
||||||
// downloaded that failed the hash-test
|
// downloaded that failed the hash-test
|
||||||
|
|
|
@ -200,7 +200,7 @@ namespace libtorrent
|
||||||
// we potentially could connect to
|
// we potentially could connect to
|
||||||
int connect_candidates;
|
int connect_candidates;
|
||||||
|
|
||||||
const std::vector<bool>* pieces;
|
bitfield const* pieces;
|
||||||
|
|
||||||
// this is the number of pieces the client has
|
// this is the number of pieces the client has
|
||||||
// downloaded. it is equal to:
|
// downloaded. it is equal to:
|
||||||
|
|
|
@ -35,6 +35,7 @@ $(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/bandwidth_limit.hpp \
|
$(top_srcdir)/include/libtorrent/bandwidth_limit.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/bandwidth_queue_entry.hpp \
|
$(top_srcdir)/include/libtorrent/bandwidth_queue_entry.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
||||||
|
$(top_srcdir)/include/libtorrent/bitfield.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/broadcast_socket.hpp \
|
$(top_srcdir)/include/libtorrent/broadcast_socket.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/buffer.hpp \
|
$(top_srcdir)/include/libtorrent/buffer.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/connection_queue.hpp \
|
$(top_srcdir)/include/libtorrent/connection_queue.hpp \
|
||||||
|
|
|
@ -937,21 +937,11 @@ namespace libtorrent
|
||||||
|
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = receive_buffer();
|
||||||
|
|
||||||
std::vector<bool> bitfield;
|
bitfield bits;
|
||||||
|
bits.borrow_bytes((char*)recv_buffer.begin
|
||||||
|
, t->valid_metadata()?get_bitfield().size():(packet_size()-1)*8);
|
||||||
|
|
||||||
if (!t->valid_metadata())
|
incoming_bitfield(bits);
|
||||||
bitfield.resize((packet_size() - 1) * 8);
|
|
||||||
else
|
|
||||||
bitfield.resize(get_bitfield().size());
|
|
||||||
|
|
||||||
// if we don't have metadata yet
|
|
||||||
// just remember the bitmask
|
|
||||||
// don't update the piecepicker
|
|
||||||
// (since it doesn't exist yet)
|
|
||||||
for (int i = 0; i < (int)bitfield.size(); ++i)
|
|
||||||
bitfield[i] = (recv_buffer[1 + (i>>3)] & (1 << (7 - (i&7)))) != 0;
|
|
||||||
|
|
||||||
incoming_bitfield(bitfield);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
@ -1426,7 +1416,7 @@ namespace libtorrent
|
||||||
send_buffer(msg, sizeof(msg));
|
send_buffer(msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_peer_connection::write_bitfield(std::vector<bool> const& bitfield)
|
void bt_peer_connection::write_bitfield(bitfield const& bits)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
@ -1459,12 +1449,14 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_pieces = bitfield.size();
|
int num_pieces = bits.size();
|
||||||
int lazy_pieces[50];
|
int lazy_pieces[50];
|
||||||
int num_lazy_pieces = 0;
|
int num_lazy_pieces = 0;
|
||||||
int lazy_piece = 0;
|
int lazy_piece = 0;
|
||||||
|
|
||||||
TORRENT_ASSERT(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
|
TORRENT_ASSERT(t->is_seed() == (bits.count()
|
||||||
|
== num_pieces));
|
||||||
|
|
||||||
if (t->is_seed() && m_ses.settings().lazy_bitfields)
|
if (t->is_seed() && m_ses.settings().lazy_bitfields)
|
||||||
{
|
{
|
||||||
num_lazy_pieces = (std::min)(50, num_pieces / 10);
|
num_lazy_pieces = (std::min)(50, num_pieces / 10);
|
||||||
|
@ -1491,7 +1483,7 @@ namespace libtorrent
|
||||||
++lazy_piece;
|
++lazy_piece;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bitfield[i]) bitfield_string << "1";
|
if (bits[i]) bitfield_string << "1";
|
||||||
else bitfield_string << "0";
|
else bitfield_string << "0";
|
||||||
}
|
}
|
||||||
bitfield_string << "\n";
|
bitfield_string << "\n";
|
||||||
|
@ -1506,18 +1498,9 @@ namespace libtorrent
|
||||||
detail::write_int32(packet_size - 4, i.begin);
|
detail::write_int32(packet_size - 4, i.begin);
|
||||||
detail::write_uint8(msg_bitfield, i.begin);
|
detail::write_uint8(msg_bitfield, i.begin);
|
||||||
|
|
||||||
std::fill(i.begin, i.end, 0);
|
memcpy(i.begin, bits.bytes(), packet_size - 5);
|
||||||
for (int c = 0; c < num_pieces; ++c)
|
for (int c = 0; c < num_lazy_pieces; ++c)
|
||||||
{
|
i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7));
|
||||||
if (lazy_piece < num_lazy_pieces
|
|
||||||
&& lazy_pieces[lazy_piece] == c)
|
|
||||||
{
|
|
||||||
++lazy_piece;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (bitfield[c])
|
|
||||||
i.begin[c >> 3] |= 1 << (7 - (c & 7));
|
|
||||||
}
|
|
||||||
TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8);
|
TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
|
@ -326,7 +326,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
bool interested = false;
|
bool interested = false;
|
||||||
const std::vector<bool>& we_have = t->pieces();
|
bitfield const& we_have = t->pieces();
|
||||||
for (int j = 0; j != (int)we_have.size(); ++j)
|
for (int j = 0; j != (int)we_have.size(); ++j)
|
||||||
{
|
{
|
||||||
if (!we_have[j]
|
if (!we_have[j]
|
||||||
|
@ -579,7 +579,7 @@ namespace libtorrent
|
||||||
m_statistics.add_stat(downloaded, uploaded);
|
m_statistics.add_stat(downloaded, uploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> const& peer_connection::get_bitfield() const
|
bitfield const& peer_connection::get_bitfield() const
|
||||||
{
|
{
|
||||||
return m_have_piece;
|
return m_have_piece;
|
||||||
}
|
}
|
||||||
|
@ -749,7 +749,7 @@ namespace libtorrent
|
||||||
// if we don't have valid metadata yet,
|
// if we don't have valid metadata yet,
|
||||||
// leave the vector unallocated
|
// leave the vector unallocated
|
||||||
TORRENT_ASSERT(m_num_pieces == 0);
|
TORRENT_ASSERT(m_num_pieces == 0);
|
||||||
std::fill(m_have_piece.begin(), m_have_piece.end(), false);
|
m_have_piece.clear_all();
|
||||||
TORRENT_ASSERT(!m_torrent.expired());
|
TORRENT_ASSERT(!m_torrent.expired());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1082,7 +1082,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_have_piece[index] = true;
|
m_have_piece.set_bit(index);
|
||||||
|
|
||||||
// only update the piece_picker if
|
// only update the piece_picker if
|
||||||
// we have the metadata and if
|
// we have the metadata and if
|
||||||
|
@ -1127,7 +1127,7 @@ namespace libtorrent
|
||||||
// --------- BITFIELD ----------
|
// --------- BITFIELD ----------
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
||||||
void peer_connection::incoming_bitfield(std::vector<bool> const& bitfield)
|
void peer_connection::incoming_bitfield(bitfield const& bits)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
@ -1138,7 +1138,7 @@ namespace libtorrent
|
||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end; ++i)
|
, end(m_extensions.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
if ((*i)->on_bitfield(bitfield)) return;
|
if ((*i)->on_bitfield(bits)) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1147,9 +1147,9 @@ namespace libtorrent
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " <== BITFIELD ";
|
(*m_logger) << time_now_string() << " <== BITFIELD ";
|
||||||
|
|
||||||
for (int i = 0; i < int(bitfield.size()); ++i)
|
for (int i = 0; i < int(bits.size()); ++i)
|
||||||
{
|
{
|
||||||
if (bitfield[i]) (*m_logger) << "1";
|
if (bits[i]) (*m_logger) << "1";
|
||||||
else (*m_logger) << "0";
|
else (*m_logger) << "0";
|
||||||
}
|
}
|
||||||
(*m_logger) << "\n";
|
(*m_logger) << "\n";
|
||||||
|
@ -1158,10 +1158,10 @@ namespace libtorrent
|
||||||
// if we don't have the metedata, we cannot
|
// if we don't have the metedata, we cannot
|
||||||
// verify the bitfield size
|
// verify the bitfield size
|
||||||
if (t->valid_metadata()
|
if (t->valid_metadata()
|
||||||
&& (bitfield.size() / 8) != (m_have_piece.size() / 8))
|
&& (bits.size() / 8) != (m_have_piece.size() / 8))
|
||||||
{
|
{
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
|
msg << "got bitfield with invalid size: " << (bits.size() / 8)
|
||||||
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
||||||
<< " bytes";
|
<< " bytes";
|
||||||
disconnect(msg.str().c_str(), 2);
|
disconnect(msg.str().c_str(), 2);
|
||||||
|
@ -1174,15 +1174,15 @@ namespace libtorrent
|
||||||
// (since it doesn't exist yet)
|
// (since it doesn't exist yet)
|
||||||
if (!t->ready_for_connections())
|
if (!t->ready_for_connections())
|
||||||
{
|
{
|
||||||
m_have_piece = bitfield;
|
m_have_piece = bits;
|
||||||
m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true);
|
m_num_pieces = bits.count();
|
||||||
if (m_peer_info) m_peer_info->seed = (m_num_pieces == int(bitfield.size()));
|
if (m_peer_info) m_peer_info->seed = (m_num_pieces == int(bits.size()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(t->valid_metadata());
|
TORRENT_ASSERT(t->valid_metadata());
|
||||||
|
|
||||||
int num_pieces = std::count(bitfield.begin(), bitfield.end(), true);
|
int num_pieces = bits.count();
|
||||||
if (num_pieces == int(m_have_piece.size()))
|
if (num_pieces == int(m_have_piece.size()))
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
@ -1197,7 +1197,7 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fill(m_have_piece.begin(), m_have_piece.end(), true);
|
m_have_piece.set_all();
|
||||||
m_num_pieces = num_pieces;
|
m_num_pieces = num_pieces;
|
||||||
t->peer_has_all();
|
t->peer_has_all();
|
||||||
if (!t->is_finished())
|
if (!t->is_finished())
|
||||||
|
@ -1211,11 +1211,11 @@ namespace libtorrent
|
||||||
bool interesting = false;
|
bool interesting = false;
|
||||||
if (!t->is_seed())
|
if (!t->is_seed())
|
||||||
{
|
{
|
||||||
t->peer_has(bitfield);
|
t->peer_has(bits);
|
||||||
|
|
||||||
for (int i = 0; i < (int)m_have_piece.size(); ++i)
|
for (int i = 0; i < (int)m_have_piece.size(); ++i)
|
||||||
{
|
{
|
||||||
bool have = bitfield[i];
|
bool have = bits[i];
|
||||||
if (have && !m_have_piece[i])
|
if (have && !m_have_piece[i])
|
||||||
{
|
{
|
||||||
if (!t->have_piece(i) && t->picker().piece_priority(i) != 0)
|
if (!t->have_piece(i) && t->picker().piece_priority(i) != 0)
|
||||||
|
@ -1229,7 +1229,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_have_piece = bitfield;
|
m_have_piece = bits;
|
||||||
m_num_pieces = num_pieces;
|
m_num_pieces = num_pieces;
|
||||||
|
|
||||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
if (interesting) t->get_policy().peer_is_interesting(*this);
|
||||||
|
@ -1764,7 +1764,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_have_piece.empty());
|
TORRENT_ASSERT(!m_have_piece.empty());
|
||||||
std::fill(m_have_piece.begin(), m_have_piece.end(), true);
|
m_have_piece.set_all();
|
||||||
m_num_pieces = m_have_piece.size();
|
m_num_pieces = m_have_piece.size();
|
||||||
|
|
||||||
t->peer_has_all();
|
t->peer_has_all();
|
||||||
|
|
|
@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "libtorrent/piece_picker.hpp"
|
#include "libtorrent/piece_picker.hpp"
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#include "libtorrent/peer_connection.hpp"
|
#include "libtorrent/peer_connection.hpp"
|
||||||
|
@ -122,16 +123,17 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// pieces is a bitmask with the pieces we have
|
// pieces is a bitmask with the pieces we have
|
||||||
void piece_picker::init(std::vector<bool> const& pieces)
|
void piece_picker::init(bitfield const& pieces)
|
||||||
{
|
{
|
||||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
m_files_checked_called = true;
|
m_files_checked_called = true;
|
||||||
#endif
|
#endif
|
||||||
for (std::vector<bool>::const_iterator i = pieces.begin();
|
int index = 0;
|
||||||
i != pieces.end(); ++i)
|
for (bitfield::const_iterator i = pieces.begin();
|
||||||
|
i != pieces.end(); ++i, ++index)
|
||||||
{
|
{
|
||||||
int index = static_cast<int>(i - pieces.begin());
|
TORRENT_ASSERT(index < pieces.size());
|
||||||
piece_pos& p = m_piece_map[index];
|
piece_pos& p = m_piece_map[index];
|
||||||
if (*i) we_have(index);
|
if (*i) we_have(index);
|
||||||
else TORRENT_ASSERT(p.index == 0);
|
else TORRENT_ASSERT(p.index == 0);
|
||||||
|
@ -214,15 +216,15 @@ namespace libtorrent
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
void piece_picker::verify_pick(std::vector<piece_block> const& picked
|
void piece_picker::verify_pick(std::vector<piece_block> const& picked
|
||||||
, std::vector<bool> const& bitfield) const
|
, bitfield const& bits) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(bitfield.size() == m_piece_map.size());
|
TORRENT_ASSERT(bits.size() == m_piece_map.size());
|
||||||
for (std::vector<piece_block>::const_iterator i = picked.begin()
|
for (std::vector<piece_block>::const_iterator i = picked.begin()
|
||||||
, end(picked.end()); i != end; ++i)
|
, end(picked.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(i->piece_index >= 0);
|
TORRENT_ASSERT(i->piece_index >= 0);
|
||||||
TORRENT_ASSERT(i->piece_index < int(bitfield.size()));
|
TORRENT_ASSERT(i->piece_index < int(bits.size()));
|
||||||
TORRENT_ASSERT(bitfield[i->piece_index]);
|
TORRENT_ASSERT(bits[i->piece_index]);
|
||||||
TORRENT_ASSERT(!m_piece_map[i->piece_index].have());
|
TORRENT_ASSERT(!m_piece_map[i->piece_index].have());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -887,14 +889,14 @@ namespace libtorrent
|
||||||
if (prev_priority >= 0) update(prev_priority, p.index);
|
if (prev_priority >= 0) update(prev_priority, p.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_picker::inc_refcount(std::vector<bool> const& bitmask)
|
void piece_picker::inc_refcount(bitfield const& bitmask)
|
||||||
{
|
{
|
||||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||||
TORRENT_ASSERT(bitmask.size() == m_piece_map.size());
|
TORRENT_ASSERT(bitmask.size() == m_piece_map.size());
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (std::vector<bool>::const_iterator i = bitmask.begin()
|
for (bitfield::const_iterator i = bitmask.begin()
|
||||||
, end(bitmask.end()); i != end; ++i, ++index)
|
, end(bitmask.end()); i != end; ++i, ++index)
|
||||||
{
|
{
|
||||||
if (*i)
|
if (*i)
|
||||||
|
@ -907,14 +909,14 @@ namespace libtorrent
|
||||||
if (updated && m_sequential_download == -1) m_dirty = true;
|
if (updated && m_sequential_download == -1) m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_picker::dec_refcount(std::vector<bool> const& bitmask)
|
void piece_picker::dec_refcount(bitfield const& bitmask)
|
||||||
{
|
{
|
||||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||||
TORRENT_ASSERT(bitmask.size() == m_piece_map.size());
|
TORRENT_ASSERT(bitmask.size() == m_piece_map.size());
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (std::vector<bool>::const_iterator i = bitmask.begin()
|
for (bitfield::const_iterator i = bitmask.begin()
|
||||||
, end(bitmask.end()); i != end; ++i, ++index)
|
, end(bitmask.end()); i != end; ++i, ++index)
|
||||||
{
|
{
|
||||||
if (*i)
|
if (*i)
|
||||||
|
@ -1156,7 +1158,7 @@ namespace libtorrent
|
||||||
// to pick blocks from the same pieces as fast peers, and vice
|
// to pick blocks from the same pieces as fast peers, and vice
|
||||||
// versa. Downloading pieces are marked as being fast, medium
|
// versa. Downloading pieces are marked as being fast, medium
|
||||||
// or slow once they're started.
|
// or slow once they're started.
|
||||||
void piece_picker::pick_pieces(const std::vector<bool>& pieces
|
void piece_picker::pick_pieces(bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, int num_blocks, int prefer_whole_pieces
|
, int num_blocks, int prefer_whole_pieces
|
||||||
, void* peer, piece_state_t speed, bool rarest_first
|
, void* peer, piece_state_t speed, bool rarest_first
|
||||||
|
@ -1279,7 +1281,7 @@ namespace libtorrent
|
||||||
, backup_blocks.begin(), backup_blocks.end());
|
, backup_blocks.begin(), backup_blocks.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool piece_picker::can_pick(int piece, std::vector<bool> const& bitmask) const
|
bool piece_picker::can_pick(int piece, bitfield const& bitmask) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(piece >= 0 && piece < int(m_piece_map.size()));
|
TORRENT_ASSERT(piece >= 0 && piece < int(m_piece_map.size()));
|
||||||
return bitmask[piece]
|
return bitmask[piece]
|
||||||
|
@ -1326,7 +1328,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int piece_picker::add_blocks(std::vector<int> const& piece_list
|
int piece_picker::add_blocks(std::vector<int> const& piece_list
|
||||||
, std::vector<bool> const& pieces
|
, bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, int num_blocks, int prefer_whole_pieces
|
, int num_blocks, int prefer_whole_pieces
|
||||||
, void* peer, std::vector<int> const& ignore) const
|
, void* peer, std::vector<int> const& ignore) const
|
||||||
|
@ -1388,7 +1390,7 @@ namespace libtorrent
|
||||||
return num_blocks;
|
return num_blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
int piece_picker::add_blocks_downloading(std::vector<bool> const& pieces
|
int piece_picker::add_blocks_downloading(bitfield const& pieces
|
||||||
, std::vector<piece_block>& interesting_blocks
|
, std::vector<piece_block>& interesting_blocks
|
||||||
, std::vector<piece_block>& backup_blocks
|
, std::vector<piece_block>& backup_blocks
|
||||||
, int num_blocks, int prefer_whole_pieces
|
, int num_blocks, int prefer_whole_pieces
|
||||||
|
@ -1580,7 +1582,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> piece_picker::expand_piece(int piece, int whole_pieces
|
std::pair<int, int> piece_picker::expand_piece(int piece, int whole_pieces
|
||||||
, std::vector<bool> const& have) const
|
, bitfield const& have) const
|
||||||
{
|
{
|
||||||
if (whole_pieces == 0) return std::make_pair(piece, piece + 1);
|
if (whole_pieces == 0) return std::make_pair(piece, piece + 1);
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ namespace libtorrent
|
||||||
busy_pieces.reserve(num_requests);
|
busy_pieces.reserve(num_requests);
|
||||||
|
|
||||||
std::vector<int> const& suggested = c.suggested_pieces();
|
std::vector<int> const& suggested = c.suggested_pieces();
|
||||||
std::vector<bool> const& bitfield = c.get_bitfield();
|
bitfield const& bits = c.get_bitfield();
|
||||||
|
|
||||||
if (c.has_peer_choked())
|
if (c.has_peer_choked())
|
||||||
{
|
{
|
||||||
|
@ -254,10 +254,10 @@ namespace libtorrent
|
||||||
std::vector<int> const& allowed_fast = c.allowed_fast();
|
std::vector<int> const& allowed_fast = c.allowed_fast();
|
||||||
|
|
||||||
// build a bitmask with only the allowed pieces in it
|
// build a bitmask with only the allowed pieces in it
|
||||||
std::vector<bool> mask(c.get_bitfield().size(), false);
|
bitfield mask(c.get_bitfield().size(), false);
|
||||||
for (std::vector<int>::const_iterator i = allowed_fast.begin()
|
for (std::vector<int>::const_iterator i = allowed_fast.begin()
|
||||||
, end(allowed_fast.end()); i != end; ++i)
|
, end(allowed_fast.end()); i != end; ++i)
|
||||||
if (bitfield[*i]) mask[*i] = true;
|
if (bits[*i]) mask.set_bit(*i);
|
||||||
|
|
||||||
p.pick_pieces(mask, interesting_pieces
|
p.pick_pieces(mask, interesting_pieces
|
||||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||||
|
@ -273,7 +273,7 @@ namespace libtorrent
|
||||||
// the last argument is if we should prefer whole pieces
|
// the last argument is if we should prefer whole pieces
|
||||||
// for this peer. If we're downloading one piece in 20 seconds
|
// for this peer. If we're downloading one piece in 20 seconds
|
||||||
// then use this mode.
|
// then use this mode.
|
||||||
p.pick_pieces(bitfield, interesting_pieces
|
p.pick_pieces(bits, interesting_pieces
|
||||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||||
, state, rarest_first, c.on_parole(), suggested);
|
, state, rarest_first, c.on_parole(), suggested);
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,7 @@ namespace libtorrent
|
||||||
" ]\n";
|
" ]\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
std::fill(m_have_pieces.begin(), m_have_pieces.end(), false);
|
m_have_pieces.clear_all();
|
||||||
m_num_pieces = 0;
|
m_num_pieces = 0;
|
||||||
m_error = j.str;
|
m_error = j.str;
|
||||||
pause();
|
pause();
|
||||||
|
@ -523,7 +523,7 @@ namespace libtorrent
|
||||||
// or the resume_data was accepted
|
// or the resume_data was accepted
|
||||||
|
|
||||||
m_num_pieces = 0;
|
m_num_pieces = 0;
|
||||||
std::fill(m_have_pieces.begin(), m_have_pieces.end(), false);
|
m_have_pieces.clear_all();
|
||||||
if (!fastresume_rejected)
|
if (!fastresume_rejected)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_resume_data.type() == entry::dictionary_t);
|
TORRENT_ASSERT(m_resume_data.type() == entry::dictionary_t);
|
||||||
|
@ -536,9 +536,9 @@ namespace libtorrent
|
||||||
std::string const& pieces_str = pieces->string();
|
std::string const& pieces_str = pieces->string();
|
||||||
for (int i = 0, end(pieces_str.size()); i < end; ++i)
|
for (int i = 0, end(pieces_str.size()); i < end; ++i)
|
||||||
{
|
{
|
||||||
bool have = pieces_str[i] & 1;
|
if ((pieces_str[i] & 1) == 0) continue;
|
||||||
m_have_pieces[i] = have;
|
m_have_pieces.set_bit(i);
|
||||||
m_num_pieces += have;
|
++m_num_pieces;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_have_pieces[piece_index])
|
if (m_have_pieces[piece_index])
|
||||||
{
|
{
|
||||||
m_have_pieces[piece_index] = false;
|
m_have_pieces.clear_bit(piece_index);
|
||||||
--m_num_pieces;
|
--m_num_pieces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +593,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (std::vector<bool>::iterator i = m_have_pieces.begin()
|
for (bitfield::const_iterator i = m_have_pieces.begin()
|
||||||
, end(m_have_pieces.end()); i != end; ++i, ++index)
|
, end(m_have_pieces.end()); i != end; ++i, ++index)
|
||||||
{
|
{
|
||||||
if (*i) m_picker->we_have(index);
|
if (*i) m_picker->we_have(index);
|
||||||
|
@ -635,7 +635,7 @@ namespace libtorrent
|
||||||
" ]\n";
|
" ]\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
std::fill(m_have_pieces.begin(), m_have_pieces.end(), false);
|
m_have_pieces.clear_all();
|
||||||
m_num_pieces = 0;
|
m_num_pieces = 0;
|
||||||
m_error = j.str;
|
m_error = j.str;
|
||||||
pause();
|
pause();
|
||||||
|
@ -647,7 +647,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (j.offset >= 0 && !m_have_pieces[j.offset])
|
if (j.offset >= 0 && !m_have_pieces[j.offset])
|
||||||
{
|
{
|
||||||
m_have_pieces[j.offset] = true;
|
m_have_pieces.set_bit(j.offset);
|
||||||
++m_num_pieces;
|
++m_num_pieces;
|
||||||
TORRENT_ASSERT(m_picker);
|
TORRENT_ASSERT(m_picker);
|
||||||
m_picker->we_have(j.offset);
|
m_picker->we_have(j.offset);
|
||||||
|
@ -1452,7 +1452,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (!m_have_pieces[index])
|
if (!m_have_pieces[index])
|
||||||
m_num_pieces++;
|
m_num_pieces++;
|
||||||
m_have_pieces[index] = true;
|
m_have_pieces.set_bit(index);
|
||||||
|
|
||||||
TORRENT_ASSERT(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0)
|
TORRENT_ASSERT(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0)
|
||||||
== m_num_pieces);
|
== m_num_pieces);
|
||||||
|
@ -1872,9 +1872,8 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (m_picker.get())
|
if (m_picker.get())
|
||||||
{
|
{
|
||||||
const std::vector<bool>& pieces = p->get_bitfield();
|
bitfield const& pieces = p->get_bitfield();
|
||||||
TORRENT_ASSERT(std::count(pieces.begin(), pieces.end(), true)
|
TORRENT_ASSERT(pieces.count() < int(pieces.size()));
|
||||||
< int(pieces.size()));
|
|
||||||
m_picker->dec_refcount(pieces);
|
m_picker->dec_refcount(pieces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,8 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
// this is always a seed
|
// this is always a seed
|
||||||
incoming_bitfield(std::vector<bool>(
|
incoming_have_all();
|
||||||
t->torrent_file().num_pieces(), true));
|
|
||||||
// it is always possible to request pieces
|
// it is always possible to request pieces
|
||||||
incoming_unchoke();
|
incoming_unchoke();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "libtorrent/piece_picker.hpp"
|
#include "libtorrent/piece_picker.hpp"
|
||||||
#include "libtorrent/policy.hpp"
|
#include "libtorrent/policy.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -12,12 +13,12 @@ using namespace libtorrent;
|
||||||
|
|
||||||
const int blocks_per_piece = 4;
|
const int blocks_per_piece = 4;
|
||||||
|
|
||||||
std::vector<bool> string2vec(char const* have_str)
|
bitfield string2vec(char const* have_str)
|
||||||
{
|
{
|
||||||
const int num_pieces = strlen(have_str);
|
const int num_pieces = strlen(have_str);
|
||||||
std::vector<bool> have(num_pieces, false);
|
bitfield have(num_pieces, false);
|
||||||
for (int i = 0; i < num_pieces; ++i)
|
for (int i = 0; i < num_pieces; ++i)
|
||||||
if (have_str[i] != ' ') have[i] = true;
|
if (have_str[i] != ' ') have.set_bit(i);
|
||||||
return have;
|
return have;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ boost::shared_ptr<piece_picker> setup_picker(
|
||||||
|
|
||||||
boost::shared_ptr<piece_picker> p(new piece_picker(blocks_per_piece, num_pieces * blocks_per_piece));
|
boost::shared_ptr<piece_picker> p(new piece_picker(blocks_per_piece, num_pieces * blocks_per_piece));
|
||||||
|
|
||||||
std::vector<bool> have = string2vec(have_str);
|
bitfield have = string2vec(have_str);
|
||||||
|
|
||||||
for (int i = 0; i < num_pieces; ++i)
|
for (int i = 0; i < num_pieces; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "libtorrent/xml_parse.hpp"
|
#include "libtorrent/xml_parse.hpp"
|
||||||
#include "libtorrent/upnp.hpp"
|
#include "libtorrent/upnp.hpp"
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
|
#include "libtorrent/bitfield.hpp"
|
||||||
#include "libtorrent/torrent_info.hpp"
|
#include "libtorrent/torrent_info.hpp"
|
||||||
#include "libtorrent/escape_string.hpp"
|
#include "libtorrent/escape_string.hpp"
|
||||||
#include "libtorrent/broadcast_socket.hpp"
|
#include "libtorrent/broadcast_socket.hpp"
|
||||||
|
@ -473,6 +474,31 @@ int test_main()
|
||||||
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 12);
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 12);
|
||||||
h2 = boost::lexical_cast<sha1_hash>("0123456789abcdef11232456789abcdef0123456");
|
h2 = boost::lexical_cast<sha1_hash>("0123456789abcdef11232456789abcdef0123456");
|
||||||
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 16 * 4 + 3);
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 16 * 4 + 3);
|
||||||
|
|
||||||
|
|
||||||
|
// test bitfield
|
||||||
|
bitfield test1(10, false);
|
||||||
|
TEST_CHECK(test1.count() == 0);
|
||||||
|
test1.set_bit(9);
|
||||||
|
TEST_CHECK(test1.count() == 1);
|
||||||
|
test1.clear_bit(9);
|
||||||
|
TEST_CHECK(test1.count() == 0);
|
||||||
|
test1.set_bit(2);
|
||||||
|
TEST_CHECK(test1.count() == 1);
|
||||||
|
test1.set_bit(1);
|
||||||
|
test1.set_bit(9);
|
||||||
|
TEST_CHECK(test1.count() == 3);
|
||||||
|
test1.clear_bit(2);
|
||||||
|
TEST_CHECK(test1.count() == 2);
|
||||||
|
int distance = std::distance(test1.begin(), test1.end());
|
||||||
|
std::cerr << distance << std::endl;
|
||||||
|
TEST_CHECK(distance == 10);
|
||||||
|
|
||||||
|
test1.set_all();
|
||||||
|
TEST_CHECK(test1.count() == 10);
|
||||||
|
|
||||||
|
test1.clear_all();
|
||||||
|
TEST_CHECK(test1.count() == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue