optimized away torrent::m_have_pieces (#62) and added some documentation on bitfield. The piece picker is now constructed with the torrent, but still freed when turned into a seed

This commit is contained in:
Arvid Norberg 2008-06-07 02:58:28 +00:00
parent bcc24bf831
commit 9d1e77dc88
12 changed files with 394 additions and 276 deletions

View File

@ -127,95 +127,96 @@
</ul> </ul>
</li> </li>
<li><a class="reference" href="#big-number" id="id109" name="id109">big_number</a></li> <li><a class="reference" href="#big-number" id="id109" name="id109">big_number</a></li>
<li><a class="reference" href="#hasher" id="id110" name="id110">hasher</a></li> <li><a class="reference" href="#bitfield" id="id110" name="id110">bitfield</a></li>
<li><a class="reference" href="#fingerprint" id="id111" name="id111">fingerprint</a></li> <li><a class="reference" href="#hasher" id="id111" name="id111">hasher</a></li>
<li><a class="reference" href="#upnp-and-nat-pmp" id="id112" name="id112">UPnP and NAT-PMP</a><ul> <li><a class="reference" href="#fingerprint" id="id112" name="id112">fingerprint</a></li>
<li><a class="reference" href="#add-mapping" id="id113" name="id113">add_mapping</a></li> <li><a class="reference" href="#upnp-and-nat-pmp" id="id113" name="id113">UPnP and NAT-PMP</a><ul>
<li><a class="reference" href="#delete-mapping" id="id114" name="id114">delete_mapping</a></li> <li><a class="reference" href="#add-mapping" id="id114" name="id114">add_mapping</a></li>
<li><a class="reference" href="#router-model" id="id115" name="id115">router_model()</a></li> <li><a class="reference" href="#delete-mapping" id="id115" name="id115">delete_mapping</a></li>
<li><a class="reference" href="#router-model" id="id116" name="id116">router_model()</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#free-functions" id="id116" name="id116">free functions</a><ul> <li><a class="reference" href="#free-functions" id="id117" name="id117">free functions</a><ul>
<li><a class="reference" href="#identify-client" id="id117" name="id117">identify_client()</a></li> <li><a class="reference" href="#identify-client" id="id118" name="id118">identify_client()</a></li>
<li><a class="reference" href="#client-fingerprint" id="id118" name="id118">client_fingerprint()</a></li> <li><a class="reference" href="#client-fingerprint" id="id119" name="id119">client_fingerprint()</a></li>
<li><a class="reference" href="#bdecode-bencode" id="id119" name="id119">bdecode() bencode()</a></li> <li><a class="reference" href="#bdecode-bencode" id="id120" name="id120">bdecode() bencode()</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#alerts" id="id120" name="id120">alerts</a><ul> <li><a class="reference" href="#alerts" id="id121" name="id121">alerts</a><ul>
<li><a class="reference" href="#external-ip-alert" id="id121" name="id121">external_ip_alert</a></li> <li><a class="reference" href="#external-ip-alert" id="id122" name="id122">external_ip_alert</a></li>
<li><a class="reference" href="#listen-failed-alert" id="id122" name="id122">listen_failed_alert</a></li> <li><a class="reference" href="#listen-failed-alert" id="id123" name="id123">listen_failed_alert</a></li>
<li><a class="reference" href="#portmap-error-alert" id="id123" name="id123">portmap_error_alert</a></li> <li><a class="reference" href="#portmap-error-alert" id="id124" name="id124">portmap_error_alert</a></li>
<li><a class="reference" href="#portmap-alert" id="id124" name="id124">portmap_alert</a></li> <li><a class="reference" href="#portmap-alert" id="id125" name="id125">portmap_alert</a></li>
<li><a class="reference" href="#file-error-alert" id="id125" name="id125">file_error_alert</a></li> <li><a class="reference" href="#file-error-alert" id="id126" name="id126">file_error_alert</a></li>
<li><a class="reference" href="#tracker-announce-alert" id="id126" name="id126">tracker_announce_alert</a></li> <li><a class="reference" href="#tracker-announce-alert" id="id127" name="id127">tracker_announce_alert</a></li>
<li><a class="reference" href="#tracker-alert" id="id127" name="id127">tracker_alert</a></li> <li><a class="reference" href="#tracker-alert" id="id128" name="id128">tracker_alert</a></li>
<li><a class="reference" href="#tracker-error-alert" id="id128" name="id128">tracker_error_alert</a></li> <li><a class="reference" href="#tracker-error-alert" id="id129" name="id129">tracker_error_alert</a></li>
<li><a class="reference" href="#tracker-reply-alert" id="id129" name="id129">tracker_reply_alert</a></li> <li><a class="reference" href="#tracker-reply-alert" id="id130" name="id130">tracker_reply_alert</a></li>
<li><a class="reference" href="#tracker-warning-alert" id="id130" name="id130">tracker_warning_alert</a></li> <li><a class="reference" href="#tracker-warning-alert" id="id131" name="id131">tracker_warning_alert</a></li>
<li><a class="reference" href="#scrape-reply-alert" id="id131" name="id131">scrape_reply_alert</a></li> <li><a class="reference" href="#scrape-reply-alert" id="id132" name="id132">scrape_reply_alert</a></li>
<li><a class="reference" href="#scrape-failed-alert" id="id132" name="id132">scrape_failed_alert</a></li> <li><a class="reference" href="#scrape-failed-alert" id="id133" name="id133">scrape_failed_alert</a></li>
<li><a class="reference" href="#url-seed-alert" id="id133" name="id133">url_seed_alert</a></li> <li><a class="reference" href="#url-seed-alert" id="id134" name="id134">url_seed_alert</a></li>
<li><a class="reference" href="#hash-failed-alert" id="id134" name="id134">hash_failed_alert</a></li> <li><a class="reference" href="#hash-failed-alert" id="id135" name="id135">hash_failed_alert</a></li>
<li><a class="reference" href="#peer-ban-alert" id="id135" name="id135">peer_ban_alert</a></li> <li><a class="reference" href="#peer-ban-alert" id="id136" name="id136">peer_ban_alert</a></li>
<li><a class="reference" href="#peer-error-alert" id="id136" name="id136">peer_error_alert</a></li> <li><a class="reference" href="#peer-error-alert" id="id137" name="id137">peer_error_alert</a></li>
<li><a class="reference" href="#invalid-request-alert" id="id137" name="id137">invalid_request_alert</a></li> <li><a class="reference" href="#invalid-request-alert" id="id138" name="id138">invalid_request_alert</a></li>
<li><a class="reference" href="#torrent-finished-alert" id="id138" name="id138">torrent_finished_alert</a></li> <li><a class="reference" href="#torrent-finished-alert" id="id139" name="id139">torrent_finished_alert</a></li>
<li><a class="reference" href="#metadata-failed-alert" id="id139" name="id139">metadata_failed_alert</a></li> <li><a class="reference" href="#metadata-failed-alert" id="id140" name="id140">metadata_failed_alert</a></li>
<li><a class="reference" href="#metadata-received-alert" id="id140" name="id140">metadata_received_alert</a></li> <li><a class="reference" href="#metadata-received-alert" id="id141" name="id141">metadata_received_alert</a></li>
<li><a class="reference" href="#fastresume-rejected-alert" id="id141" name="id141">fastresume_rejected_alert</a></li> <li><a class="reference" href="#fastresume-rejected-alert" id="id142" name="id142">fastresume_rejected_alert</a></li>
<li><a class="reference" href="#peer-blocked-alert" id="id142" name="id142">peer_blocked_alert</a></li> <li><a class="reference" href="#peer-blocked-alert" id="id143" name="id143">peer_blocked_alert</a></li>
<li><a class="reference" href="#storage-moved-alert" id="id143" name="id143">storage_moved_alert</a></li> <li><a class="reference" href="#storage-moved-alert" id="id144" name="id144">storage_moved_alert</a></li>
<li><a class="reference" href="#torrent-paused-alert" id="id144" name="id144">torrent_paused_alert</a></li> <li><a class="reference" href="#torrent-paused-alert" id="id145" name="id145">torrent_paused_alert</a></li>
<li><a class="reference" href="#save-resume-data-alert" id="id145" name="id145">save_resume_data_alert</a></li> <li><a class="reference" href="#save-resume-data-alert" id="id146" name="id146">save_resume_data_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id146" name="id146">dispatcher</a></li> <li><a class="reference" href="#dispatcher" id="id147" name="id147">dispatcher</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#exceptions" id="id147" name="id147">exceptions</a><ul> <li><a class="reference" href="#exceptions" id="id148" name="id148">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id148" name="id148">invalid_handle</a></li> <li><a class="reference" href="#invalid-handle" id="id149" name="id149">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id149" name="id149">duplicate_torrent</a></li> <li><a class="reference" href="#duplicate-torrent" id="id150" name="id150">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id150" name="id150">invalid_encoding</a></li> <li><a class="reference" href="#invalid-encoding" id="id151" name="id151">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id151" name="id151">type_error</a></li> <li><a class="reference" href="#type-error" id="id152" name="id152">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id152" name="id152">invalid_torrent_file</a></li> <li><a class="reference" href="#invalid-torrent-file" id="id153" name="id153">invalid_torrent_file</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#storage-interface" id="id153" name="id153">storage_interface</a><ul> <li><a class="reference" href="#storage-interface" id="id154" name="id154">storage_interface</a><ul>
<li><a class="reference" href="#initialize" id="id154" name="id154">initialize()</a></li> <li><a class="reference" href="#initialize" id="id155" name="id155">initialize()</a></li>
<li><a class="reference" href="#read" id="id155" name="id155">read()</a></li> <li><a class="reference" href="#read" id="id156" name="id156">read()</a></li>
<li><a class="reference" href="#write" id="id156" name="id156">write()</a></li> <li><a class="reference" href="#write" id="id157" name="id157">write()</a></li>
<li><a class="reference" href="#id11" id="id157" name="id157">move_storage()</a></li> <li><a class="reference" href="#id11" id="id158" name="id158">move_storage()</a></li>
<li><a class="reference" href="#verify-resume-data" id="id158" name="id158">verify_resume_data()</a></li> <li><a class="reference" href="#verify-resume-data" id="id159" name="id159">verify_resume_data()</a></li>
<li><a class="reference" href="#write-resume-data" id="id159" name="id159">write_resume_data()</a></li> <li><a class="reference" href="#write-resume-data" id="id160" name="id160">write_resume_data()</a></li>
<li><a class="reference" href="#move-slot" id="id160" name="id160">move_slot()</a></li> <li><a class="reference" href="#move-slot" id="id161" name="id161">move_slot()</a></li>
<li><a class="reference" href="#swap-slots" id="id161" name="id161">swap_slots()</a></li> <li><a class="reference" href="#swap-slots" id="id162" name="id162">swap_slots()</a></li>
<li><a class="reference" href="#swap-slots3" id="id162" name="id162">swap_slots3()</a></li> <li><a class="reference" href="#swap-slots3" id="id163" name="id163">swap_slots3()</a></li>
<li><a class="reference" href="#hash-for-slot" id="id163" name="id163">hash_for_slot()</a></li> <li><a class="reference" href="#hash-for-slot" id="id164" name="id164">hash_for_slot()</a></li>
<li><a class="reference" href="#release-files" id="id164" name="id164">release_files()</a></li> <li><a class="reference" href="#release-files" id="id165" name="id165">release_files()</a></li>
<li><a class="reference" href="#delete-files" id="id165" name="id165">delete_files()</a></li> <li><a class="reference" href="#delete-files" id="id166" name="id166">delete_files()</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#queuing" id="id166" name="id166">queuing</a><ul> <li><a class="reference" href="#queuing" id="id167" name="id167">queuing</a><ul>
<li><a class="reference" href="#downloading" id="id167" name="id167">downloading</a></li> <li><a class="reference" href="#downloading" id="id168" name="id168">downloading</a></li>
<li><a class="reference" href="#seeding" id="id168" name="id168">seeding</a></li> <li><a class="reference" href="#seeding" id="id169" name="id169">seeding</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#fast-resume" id="id169" name="id169">fast resume</a><ul> <li><a class="reference" href="#fast-resume" id="id170" name="id170">fast resume</a><ul>
<li><a class="reference" href="#file-format" id="id170" name="id170">file format</a></li> <li><a class="reference" href="#file-format" id="id171" name="id171">file format</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#threads" id="id171" name="id171">threads</a></li> <li><a class="reference" href="#threads" id="id172" name="id172">threads</a></li>
<li><a class="reference" href="#storage-allocation" id="id172" name="id172">storage allocation</a><ul> <li><a class="reference" href="#storage-allocation" id="id173" name="id173">storage allocation</a><ul>
<li><a class="reference" href="#sparse-allocation" id="id173" name="id173">sparse allocation</a></li> <li><a class="reference" href="#sparse-allocation" id="id174" name="id174">sparse allocation</a></li>
<li><a class="reference" href="#full-allocation" id="id174" name="id174">full allocation</a></li> <li><a class="reference" href="#full-allocation" id="id175" name="id175">full allocation</a></li>
<li><a class="reference" href="#compact-allocation" id="id175" name="id175">compact allocation</a></li> <li><a class="reference" href="#compact-allocation" id="id176" name="id176">compact allocation</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#extensions" id="id176" name="id176">extensions</a><ul> <li><a class="reference" href="#extensions" id="id177" name="id177">extensions</a><ul>
<li><a class="reference" href="#metadata-from-peers" id="id177" name="id177">metadata from peers</a></li> <li><a class="reference" href="#metadata-from-peers" id="id178" name="id178">metadata from peers</a></li>
<li><a class="reference" href="#http-seeding" id="id178" name="id178">HTTP seeding</a></li> <li><a class="reference" href="#http-seeding" id="id179" name="id179">HTTP seeding</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#filename-checks" id="id179" name="id179">filename checks</a></li> <li><a class="reference" href="#filename-checks" id="id180" name="id180">filename checks</a></li>
<li><a class="reference" href="#acknowledgments" id="id180" name="id180">acknowledgments</a></li> <li><a class="reference" href="#acknowledgments" id="id181" name="id181">acknowledgments</a></li>
</ul> </ul>
</div> </div>
<div class="section"> <div class="section">
@ -2236,7 +2237,7 @@ struct torrent_status
int connect_candidates; int connect_candidates;
const std::vector&lt;bool&gt;* pieces; bitfield pieces;
int num_pieces; int num_pieces;
size_type total_done; size_type total_done;
@ -2482,7 +2483,7 @@ struct peer_info
size_type total_download; size_type total_download;
size_type total_upload; size_type total_upload;
peer_id pid; peer_id pid;
std::vector&lt;bool&gt; pieces; bitfield pieces;
int upload_limit; int upload_limit;
int download_limit; int download_limit;
@ -2686,9 +2687,9 @@ the payload data.</p>
<p><tt class="docutils literal"><span class="pre">pid</span></tt> is the peer's id as used in the bit torrent protocol. This id can be used to <p><tt class="docutils literal"><span class="pre">pid</span></tt> is the peer's id as used in the bit torrent protocol. This id can be used to
extract 'fingerprints' from the peer. Sometimes it can tell you which client the peer extract 'fingerprints' from the peer. Sometimes it can tell you which client the peer
is using. See identify_client()_</p> is using. See identify_client()_</p>
<p><tt class="docutils literal"><span class="pre">pieces</span></tt> is a vector of booleans that has as many entries as there are pieces <p><tt class="docutils literal"><span class="pre">pieces</span></tt> is a bitfield, with one bit per piece in the torrent.
in the torrent. Each boolean tells you if the peer has that piece (if it's set to true) Each bit tells you if the peer has that piece (if it's set to 1)
or if the peer miss that piece (set to false).</p> or if the peer miss that piece (set to 0).</p>
<p><tt class="docutils literal"><span class="pre">seed</span></tt> is true if this peer is a seed.</p> <p><tt class="docutils literal"><span class="pre">seed</span></tt> is true if this peer is a seed.</p>
<p><tt class="docutils literal"><span class="pre">upload_limit</span></tt> is the number of bytes per second we are allowed to send to this <p><tt class="docutils literal"><span class="pre">upload_limit</span></tt> is the number of bytes per second we are allowed to send to this
peer every second. It may be -1 if there's no local limit on the peer. The global peer every second. It may be -1 if there's no local limit on the peer. The global
@ -3235,6 +3236,50 @@ public:
<p>The iterators gives you access to individual bytes.</p> <p>The iterators gives you access to individual bytes.</p>
</div> </div>
<div class="section"> <div class="section">
<h1><a id="bitfield" name="bitfield">bitfield</a></h1>
<p>The bitfiled type stores any number of bits as a bitfield in an array.</p>
<pre class="literal-block">
class bitfield
{
bitfield();
bitfield(int bits);
bitfield(int bits, bool val);
bitfield(char const* bytes, int bits);
bitfield(bitfield const&amp; rhs);
void borrow_bytes(char* bytes, int bits);
~bitfield();
void assign(char const* bytes, int bits);
bool operator[](int index) const;
bool get_bit(int index) const;
void clear_bit(int index);
void set_bit(int index);
std::size_t size() const;
bool empty() const;
char const* bytes() const;
bitfield&amp; operator=(bitfield const&amp; rhs);
int count() const;
typedef const_iterator;
const_iterator begin() const;
const_iterator end() const;
void resize(int bits, bool val);
void set_all();
void clear_all();
void resize(int bits);
};
</pre>
</div>
<div class="section">
<h1><a id="hasher" name="hasher">hasher</a></h1> <h1><a id="hasher" name="hasher">hasher</a></h1>
<p>This class creates sha1-hashes. Its declaration looks like this:</p> <p>This class creates sha1-hashes. Its declaration looks like this:</p>
<pre class="literal-block"> <pre class="literal-block">

View File

@ -2197,7 +2197,7 @@ It contains the following fields::
int connect_candidates; int connect_candidates;
const std::vector<bool>* pieces; bitfield pieces;
int num_pieces; int num_pieces;
size_type total_done; size_type total_done;
@ -2466,7 +2466,7 @@ It contains the following fields::
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;
@ -2642,9 +2642,9 @@ the payload data.
extract 'fingerprints' from the peer. Sometimes it can tell you which client the peer extract 'fingerprints' from the peer. Sometimes it can tell you which client the peer
is using. See identify_client()_ is using. See identify_client()_
``pieces`` is a vector of booleans that has as many entries as there are pieces ``pieces`` is a bitfield, with one bit per piece in the torrent.
in the torrent. Each boolean tells you if the peer has that piece (if it's set to true) Each bit tells you if the peer has that piece (if it's set to 1)
or if the peer miss that piece (set to false). or if the peer miss that piece (set to 0).
``seed`` is true if this peer is a seed. ``seed`` is true if this peer is a seed.
@ -3291,6 +3291,53 @@ Both the ``peer_id`` and ``sha1_hash`` types are typedefs of the class
The iterators gives you access to individual bytes. The iterators gives you access to individual bytes.
bitfield
========
The bitfiled type stores any number of bits as a bitfield in an array.
::
class bitfield
{
bitfield();
bitfield(int bits);
bitfield(int bits, bool val);
bitfield(char const* bytes, int bits);
bitfield(bitfield const& rhs);
void borrow_bytes(char* bytes, int bits);
~bitfield();
void assign(char const* bytes, int bits);
bool operator[](int index) const;
bool get_bit(int index) const;
void clear_bit(int index);
void set_bit(int index);
std::size_t size() const;
bool empty() const;
char const* bytes() const;
bitfield& operator=(bitfield const& rhs);
int count() const;
typedef const_iterator;
const_iterator begin() const;
const_iterator end() const;
void resize(int bits, bool val);
void set_all();
void clear_all();
void resize(int bits);
};
hasher hasher
====== ======

View File

@ -1317,8 +1317,8 @@ int main(int ac, char* av[])
out.fill(' '); out.fill(' ');
out << (s.progress*100) << "% "; out << (s.progress*100) << "% ";
out << progress_bar(s.progress, terminal_width - 37, progress_bar_color) << "\n"; out << progress_bar(s.progress, terminal_width - 37, progress_bar_color) << "\n";
if (print_piece_bar && s.progress < 1.f && s.pieces) if (print_piece_bar && s.progress < 1.f)
out << " " << piece_bar(*s.pieces, terminal_width - 5) << "\n"; out << " " << piece_bar(s.pieces, terminal_width - 5) << "\n";
out << " peers: " << esc("37") << s.num_peers << esc("0") << " (" << esc("37") << s.connect_candidates << esc("0") << ") " out << " peers: " << esc("37") << s.num_peers << esc("0") << " (" << esc("37") << s.connect_candidates << esc("0") << ") "
<< "seeds: " << esc("37") << s.num_seeds << esc("0") << " " << "seeds: " << esc("37") << s.num_seeds << esc("0") << " "
<< "distributed copies: " << esc("37") << s.distributed_copies << esc("0") << "distributed copies: " << esc("37") << s.distributed_copies << esc("0")

View File

@ -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(bitfield const& bits); void write_bitfield();
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();

View File

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

View File

@ -378,14 +378,15 @@ namespace libtorrent
// returns true if we have downloaded the given piece // returns true if we have downloaded the given piece
bool have_piece(int index) const bool have_piece(int index) const
{ {
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size()); return has_picker()?m_picker->have_piece(index):true;
return m_have_pieces[index];
} }
bitfield const& pieces() const int num_pieces() const
{ return m_have_pieces; } {
return has_picker()
int num_pieces() const { return m_num_pieces; } ?m_picker->num_have()
:m_torrent_file->num_pieces();
}
// when we get a have message, this is called for that piece // when we get a have message, this is called for that piece
void peer_has(int index) void peer_has(int index)
@ -393,7 +394,6 @@ namespace libtorrent
if (m_picker.get()) if (m_picker.get())
{ {
TORRENT_ASSERT(!is_seed()); TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->inc_refcount(index); m_picker->inc_refcount(index);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -440,7 +440,6 @@ namespace libtorrent
if (m_picker.get()) if (m_picker.get())
{ {
TORRENT_ASSERT(!is_seed()); TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->dec_refcount(index); m_picker->dec_refcount(index);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -507,7 +506,9 @@ namespace libtorrent
bool is_seed() const bool is_seed() const
{ {
return valid_metadata() 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 // this is true if we have all the pieces that we want
@ -515,7 +516,7 @@ namespace libtorrent
{ {
if (is_seed()) return true; if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_pieces() return valid_metadata() && m_torrent_file->num_pieces()
- m_num_pieces - m_picker->num_filtered() == 0; - m_picker->num_have() - m_picker->num_filtered() == 0;
} }
fs::path save_path() const; fs::path save_path() const;
@ -741,9 +742,6 @@ namespace libtorrent
std::vector<announce_entry> m_trackers; std::vector<announce_entry> m_trackers;
// this is an index into 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 // the number of bytes that has been
// downloaded that failed the hash-test // downloaded that failed the hash-test
size_type m_total_failed_bytes; size_type m_total_failed_bytes;
@ -782,11 +780,6 @@ namespace libtorrent
float m_progress; 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 // the upload/download ratio that each peer
// tries to maintain. // tries to maintain.
// 0 is infinite // 0 is infinite

View File

@ -100,7 +100,6 @@ namespace libtorrent
, num_incomplete(-1) , num_incomplete(-1)
, list_seeds(0) , list_seeds(0)
, list_peers(0) , list_peers(0)
, pieces(0)
, num_pieces(0) , num_pieces(0)
, total_done(0) , total_done(0)
, total_wanted_done(0) , total_wanted_done(0)
@ -201,7 +200,7 @@ namespace libtorrent
// we potentially could connect to // we potentially could connect to
int connect_candidates; int connect_candidates;
bitfield const* pieces; bitfield 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:

View File

@ -245,7 +245,7 @@ namespace libtorrent
{ {
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
write_bitfield(t->pieces()); write_bitfield();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht) if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port); write_dht_port(m_ses.get_dht_settings().service_port);
@ -1416,7 +1416,7 @@ namespace libtorrent
send_buffer(msg, sizeof(msg)); send_buffer(msg, sizeof(msg));
} }
void bt_peer_connection::write_bitfield(bitfield const& bits) void bt_peer_connection::write_bitfield()
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -1449,14 +1449,11 @@ namespace libtorrent
return; return;
} }
int num_pieces = bits.size(); int num_pieces = t->picker().num_pieces();
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() == (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);
@ -1470,26 +1467,6 @@ namespace libtorrent
lazy_piece = 0; 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; const int packet_size = (num_pieces + 7) / 8 + 5;
buffer::interval i = allocate_send_buffer(packet_size); buffer::interval i = allocate_send_buffer(packet_size);
@ -1498,15 +1475,46 @@ 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);
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) for (int c = 0; c < num_lazy_pieces; ++c)
i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7)); i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7));
TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8); 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 #ifndef NDEBUG
m_sent_bitfield = true; m_sent_bitfield = true;
#endif #endif
setup_send();
if (num_lazy_pieces > 0) if (num_lazy_pieces > 0)
{ {
@ -1522,6 +1530,7 @@ namespace libtorrent
if (m_supports_fast) if (m_supports_fast)
send_allowed_set(); send_allowed_set();
setup_send();
} }
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
@ -2377,7 +2386,7 @@ namespace libtorrent
// sent the handshake // sent the handshake
if (!is_local()) write_handshake(); if (!is_local()) write_handshake();
// if (t->valid_metadata()) // if (t->valid_metadata())
// write_bitfield(t->pieces()); // write_bitfield();
if (is_disconnecting()) return; if (is_disconnecting()) return;
@ -2511,7 +2520,7 @@ namespace libtorrent
reset_recv_buffer(5); reset_recv_buffer(5);
if (t->valid_metadata()) if (t->valid_metadata())
{ {
write_bitfield(t->pieces()); write_bitfield();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht) if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port); write_dht_port(m_ses.get_dht_settings().service_port);

View File

@ -326,15 +326,19 @@ namespace libtorrent
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
bool interested = false; bool interested = false;
bitfield const& we_have = t->pieces(); if (!t->is_finished())
for (int j = 0; j != (int)we_have.size(); ++j)
{ {
if (!we_have[j] piece_picker const& p = t->picker();
&& t->piece_priority(j) > 0 int num_pieces = p.num_pieces();
&& m_have_piece[j]) for (int j = 0; j != num_pieces; ++j)
{ {
interested = true; if (!p.have_piece(j)
break; && t->piece_priority(j) > 0
&& m_have_piece[j])
{
interested = true;
break;
}
} }
} }
try try

View File

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

View File

@ -164,7 +164,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_ses(ses) , m_ses(ses)
, m_picker(0) , m_picker(new piece_picker())
, m_trackers(m_torrent_file->trackers()) , m_trackers(m_torrent_file->trackers())
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
, m_total_redundant_bytes(0) , m_total_redundant_bytes(0)
@ -175,7 +175,6 @@ namespace libtorrent
, m_settings(ses.settings()) , m_settings(ses.settings())
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_progress(0.f) , m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f) , m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
@ -240,7 +239,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_ses(ses) , m_ses(ses)
, m_picker(0) , m_picker(new piece_picker())
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
, m_total_redundant_bytes(0) , m_total_redundant_bytes(0)
, m_net_interface(net_interface.address(), 0) , m_net_interface(net_interface.address(), 0)
@ -250,7 +249,6 @@ namespace libtorrent
, m_settings(ses.settings()) , m_settings(ses.settings())
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_progress(0.f) , m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f) , m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
@ -409,16 +407,14 @@ namespace libtorrent
TORRENT_ASSERT(m_torrent_file->num_files() > 0); TORRENT_ASSERT(m_torrent_file->num_files() > 0);
TORRENT_ASSERT(m_torrent_file->total_size() >= 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 // the shared_from_this() will create an intentional
// cycle of ownership, se the hpp file for description. // cycle of ownership, se the hpp file for description.
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file 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_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
, m_storage_mode); , m_storage_mode);
m_storage = m_owning_storage.get(); m_storage = m_owning_storage.get();
m_picker.reset(new piece_picker( m_picker->init(m_torrent_file->piece_length() / m_block_size
m_torrent_file->piece_length() / m_block_size , int((m_torrent_file->total_size()+m_block_size-1)/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::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
@ -475,8 +471,6 @@ namespace libtorrent
" ]\n"; " ]\n";
#endif #endif
} }
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str; m_error = j.str;
pause(); pause();
return; return;
@ -550,8 +544,6 @@ namespace libtorrent
// there are either no files for this torrent // there are either no files for this torrent
// or the resume_data was accepted // or the resume_data was accepted
m_num_pieces = 0;
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);
@ -565,8 +557,7 @@ namespace libtorrent
for (int i = 0, end(pieces_str.size()); i < end; ++i) for (int i = 0, end(pieces_str.size()); i < end; ++i)
{ {
if ((pieces_str[i] & 1) == 0) continue; if ((pieces_str[i] & 1) == 0) continue;
m_have_pieces.set_bit(i); m_picker->we_have(i);
++m_num_pieces;
} }
} }
@ -589,11 +580,8 @@ namespace libtorrent
if (piece_index < 0 || piece_index >= torrent_file().num_pieces()) if (piece_index < 0 || piece_index >= torrent_file().num_pieces())
continue; continue;
if (m_have_pieces[piece_index]) if (m_picker->have_piece(piece_index))
{ m_picker->we_dont_have(piece_index);
m_have_pieces.clear_bit(piece_index);
--m_num_pieces;
}
entry const* bitmask_ent = i->find_key("bitmask"); entry const* bitmask_ent = i->find_key("bitmask");
if (bitmask_ent == 0 || bitmask_ent->type() != entry::string_t) break; if (bitmask_ent == 0 || bitmask_ent->type() != entry::string_t) break;
@ -619,13 +607,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(); files_checked();
@ -663,8 +644,6 @@ namespace libtorrent
" ]\n"; " ]\n";
#endif #endif
} }
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str; m_error = j.str;
pause(); pause();
m_ses.done_checking(shared_from_this()); m_ses.done_checking(shared_from_this());
@ -673,13 +652,9 @@ namespace libtorrent
m_progress = j.piece / float(torrent_file().num_pieces()); m_progress = j.piece / float(torrent_file().num_pieces());
if (j.offset >= 0 && !m_have_pieces[j.offset]) TORRENT_ASSERT(m_picker);
{ if (j.offset >= 0 && !m_picker->have_piece(j.offset))
m_have_pieces.set_bit(j.offset);
++m_num_pieces;
TORRENT_ASSERT(m_picker);
m_picker->we_have(j.offset); m_picker->we_have(j.offset);
}
// we're not done checking yet // we're not done checking yet
// this handler will be called repeatedly until // this handler will be called repeatedly until
@ -984,12 +959,12 @@ namespace libtorrent
const int last_piece = m_torrent_file->num_pieces() - 1; const int last_piece = m_torrent_file->num_pieces() - 1;
size_type total_done size_type total_done
= size_type(m_num_pieces) * m_torrent_file->piece_length(); = size_type(num_pieces()) * m_torrent_file->piece_length();
// if we have the last piece, we have to correct // if we have the last piece, we have to correct
// the amount we have, since the first calculation // the amount we have, since the first calculation
// assumed all pieces were of equal size // 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) int corr = m_torrent_file->piece_size(last_piece)
- m_torrent_file->piece_length(); - m_torrent_file->piece_length();
@ -1015,19 +990,19 @@ namespace libtorrent
return make_tuple(m_torrent_file->total_size() return make_tuple(m_torrent_file->total_size()
, m_torrent_file->total_size()); , m_torrent_file->total_size());
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_pieces() >= m_picker->num_have_filtered());
size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered()) size_type wanted_done = size_type(num_pieces() - m_picker->num_have_filtered())
* piece_size; * piece_size;
TORRENT_ASSERT(wanted_done >= 0); TORRENT_ASSERT(wanted_done >= 0);
size_type total_done size_type total_done
= size_type(m_num_pieces) * piece_size; = size_type(num_pieces()) * piece_size;
TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces()); TORRENT_ASSERT(num_pieces() < m_torrent_file->num_pieces());
// if we have the last piece, we have to correct // if we have the last piece, we have to correct
// the amount we have, since the first calculation // the amount we have, since the first calculation
// assumed all pieces were of equal size // 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); TORRENT_ASSERT(total_done >= piece_size);
int corr = m_torrent_file->piece_size(last_piece) int corr = m_torrent_file->piece_size(last_piece)
@ -1056,7 +1031,7 @@ namespace libtorrent
{ {
int corr = 0; int corr = 0;
int index = i->index; 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)); TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index));
#ifndef NDEBUG #ifndef NDEBUG
@ -1101,7 +1076,7 @@ namespace libtorrent
= pc->downloading_piece_progress(); = pc->downloading_piece_progress();
if (p) if (p)
{ {
if (m_have_pieces[p->piece_index]) if (m_picker->have_piece(p->piece_index))
continue; continue;
piece_block block(p->piece_index, p->block_index); piece_block block(p->piece_index, p->block_index);
@ -1138,16 +1113,16 @@ namespace libtorrent
wanted_done += i->second; wanted_done += i->second;
} }
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
#ifndef NDEBUG #ifndef NDEBUG
if (total_done >= m_torrent_file->total_size()) if (total_done >= m_torrent_file->total_size())
{ {
// Thist happens when a piece has been downloaded completely // Thist happens when a piece has been downloaded completely
// but not yet verified against the hash // but not yet verified against the hash
std::copy(m_have_pieces.begin(), m_have_pieces.end() std::cerr << "num_pieces: " << num_pieces() << std::endl;
, std::ostream_iterator<bool>(std::cerr, " "));
std::cerr << std::endl;
std::cerr << "num_pieces: " << m_num_pieces << std::endl;
std::cerr << "unfinished:" << std::endl; std::cerr << "unfinished:" << std::endl;
@ -1352,7 +1327,7 @@ namespace libtorrent
m_picker->restore_piece(index); m_picker->restore_piece(index);
TORRENT_ASSERT(m_storage); TORRENT_ASSERT(m_storage);
TORRENT_ASSERT(m_have_pieces[index] == false); TORRENT_ASSERT(m_picker->have_piece(index) == false);
#ifndef NDEBUG #ifndef NDEBUG
for (std::vector<void*>::iterator i = downloaders.begin() for (std::vector<void*>::iterator i = downloaders.begin()
@ -1488,13 +1463,6 @@ namespace libtorrent
std::set<void*> peers; std::set<void*> peers;
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); 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); m_picker->we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index); (*i)->announce_piece(index);
@ -1560,7 +1528,7 @@ namespace libtorrent
bool was_finished = is_finished(); bool was_finished = is_finished();
bool filter_updated = m_picker->set_piece_priority(index, priority); bool filter_updated = m_picker->set_piece_priority(index, priority);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_pieces() >= m_picker->num_have_filtered());
if (filter_updated) update_peer_interest(was_finished); if (filter_updated) update_peer_interest(was_finished);
} }
@ -1598,7 +1566,7 @@ namespace libtorrent
TORRENT_ASSERT(*i >= 0); TORRENT_ASSERT(*i >= 0);
TORRENT_ASSERT(*i <= 7); TORRENT_ASSERT(*i <= 7);
filter_updated |= m_picker->set_piece_priority(index, *i); filter_updated |= m_picker->set_piece_priority(index, *i);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_pieces() >= m_picker->num_have_filtered());
} }
if (filter_updated) update_peer_interest(was_finished); if (filter_updated) update_peer_interest(was_finished);
} }
@ -2444,8 +2412,16 @@ namespace libtorrent
// write have bitmask // write have bitmask
entry::string_type& pieces = ret["pieces"].string(); entry::string_type& pieces = ret["pieces"].string();
pieces.resize(m_torrent_file->num_pieces()); pieces.resize(m_torrent_file->num_pieces());
for (int i = 0, end(pieces.size()); i < end; ++i) if (is_seed())
pieces[i] = m_have_pieces[i] ? 1 : 0; {
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 // write local peers
@ -3119,7 +3095,6 @@ namespace libtorrent
if (!is_seed()) if (!is_seed())
{ {
m_picker->init(m_have_pieces);
if (m_sequential_download) if (m_sequential_download)
picker().sequential_download(m_sequential_download); picker().sequential_download(m_sequential_download);
} }
@ -3293,16 +3268,16 @@ namespace libtorrent
if (!m_picker->is_downloaded(i->first)) if (!m_picker->is_downloaded(i->first))
TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
} }
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_pieces() >= m_picker->num_have_filtered());
} }
if (valid_metadata()) 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 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() for (policy::const_iterator i = m_policy.begin_peer()
@ -3317,7 +3292,7 @@ namespace libtorrent
if (is_seed()) if (is_seed())
TORRENT_ASSERT(total_done == m_torrent_file->total_size()); TORRENT_ASSERT(total_done == m_torrent_file->total_size());
else else
TORRENT_ASSERT(total_done != m_torrent_file->total_size()); TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked);
} }
else else
{ {
@ -3348,8 +3323,6 @@ namespace libtorrent
} }
// This check is very expensive. // 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_block_size > 0);
TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % 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); // if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
@ -3821,7 +3794,7 @@ namespace libtorrent
TORRENT_ASSERT(m_storage->refcount() > 0); TORRENT_ASSERT(m_storage->refcount() > 0);
TORRENT_ASSERT(piece_index >= 0); TORRENT_ASSERT(piece_index >= 0);
TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces()); 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 #ifndef NDEBUG
if (m_picker) if (m_picker)
{ {
@ -3872,6 +3845,12 @@ namespace libtorrent
TORRENT_ASSERT(valid_metadata()); TORRENT_ASSERT(valid_metadata());
fp.clear(); fp.clear();
if (is_seed())
{
fp.resize(m_torrent_file->num_files(), 1.f);
return;
}
fp.resize(m_torrent_file->num_files(), 0.f); fp.resize(m_torrent_file->num_files(), 0.f);
for (int i = 0; i < m_torrent_file->num_files(); ++i) for (int i = 0; i < m_torrent_file->num_files(); ++i)
@ -3892,7 +3871,7 @@ namespace libtorrent
{ {
size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece) size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece)
- ret.start), size); - 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.piece;
ret.start = 0; ret.start = 0;
size -= bytes_step; size -= bytes_step;
@ -3907,11 +3886,6 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
TORRENT_ASSERT(std::accumulate(
m_have_pieces.begin()
, m_have_pieces.end()
, 0) == m_num_pieces);
ptime now = time_now(); ptime now = time_now();
torrent_status st; torrent_status st;
@ -4038,8 +4012,14 @@ namespace libtorrent
else st.progress = st.total_wanted_done else st.progress = st.total_wanted_done
/ static_cast<float>(st.total_wanted); / static_cast<float>(st.total_wanted);
st.pieces = &m_have_pieces; if (has_picker())
st.num_pieces = m_num_pieces; {
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_pieces();
st.num_seeds = num_seeds(); st.num_seeds = num_seeds();
if (m_picker.get()) if (m_picker.get())
st.distributed_copies = m_picker->distributed_copies(); st.distributed_copies = m_picker->distributed_copies();

View File

@ -36,7 +36,8 @@ boost::shared_ptr<piece_picker> setup_picker(
const int num_pieces = strlen(availability); const int num_pieces = strlen(availability);
assert(int(strlen(have_str)) == num_pieces); assert(int(strlen(have_str)) == num_pieces);
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);
p->init(blocks_per_piece, num_pieces * blocks_per_piece);
bitfield have = string2vec(have_str); bitfield have = string2vec(have_str);
@ -93,11 +94,10 @@ boost::shared_ptr<piece_picker> setup_picker(
TEST_CHECK(p->piece_priority(i) == prio); TEST_CHECK(p->piece_priority(i) == prio);
} }
p->init(have);
for (int i = 0; i < num_pieces; ++i) for (int i = 0; i < num_pieces; ++i)
{ {
if (!have[i]) continue; if (!have[i]) continue;
p->we_have(i);
for (int j = 0; j < blocks_per_piece; ++j) for (int j = 0; j < blocks_per_piece; ++j)
TEST_CHECK(p->is_finished(piece_block(i, j))); TEST_CHECK(p->is_finished(piece_block(i, j)));
} }
@ -152,6 +152,11 @@ void print_pick(std::vector<piece_block> const& picked)
std::cout << std::endl; std::cout << std::endl;
} }
void print_title(char const* name)
{
std::cerr << "==== " << name << " ====\n";
}
int test_pick(boost::shared_ptr<piece_picker> const& p) int test_pick(boost::shared_ptr<piece_picker> const& p)
{ {
std::vector<piece_block> picked; std::vector<piece_block> picked;
@ -174,6 +179,7 @@ int test_main()
// make sure the block that is picked is from piece 1, since it // make sure the block that is picked is from piece 1, since it
// it is the piece with the lowest availability // it is the piece with the lowest availability
print_title("test pick lowest availability");
p = setup_picker("2223333", "* * * ", "", ""); p = setup_picker("2223333", "* * * ", "", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("*******"), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector); p->pick_pieces(string2vec("*******"), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
@ -185,6 +191,7 @@ int test_main()
// make sure the block that is picked is from piece 5, since it // make sure the block that is picked is from piece 5, since it
// has the highest priority among the available pieces // has the highest priority among the available pieces
print_title("test pick highest priority");
p = setup_picker("1111111", "* * * ", "1111122", ""); p = setup_picker("1111111", "* * * ", "1111122", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("****** "), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector); p->pick_pieces(string2vec("****** "), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
@ -196,6 +203,7 @@ int test_main()
// make sure the 4 blocks are picked from the same piece if // make sure the 4 blocks are picked from the same piece if
// whole pieces are preferred. The only whole piece is 1. // whole pieces are preferred. The only whole piece is 1.
print_title("test pick whole pieces");
p = setup_picker("1111111", " ", "1111111", "1023460"); p = setup_picker("1111111", " ", "1111111", "1023460");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("****** "), picked, 1, 1, &peer_struct, piece_picker::fast, true, true, empty_vector); p->pick_pieces(string2vec("****** "), picked, 1, 1, &peer_struct, piece_picker::fast, true, true, empty_vector);
@ -209,6 +217,7 @@ int test_main()
// test the distributed copies function. It should include ourself // test the distributed copies function. It should include ourself
// in the availability. i.e. piece 0 has availability 2. // in the availability. i.e. piece 0 has availability 2.
// there are 2 pieces with availability 2 and 5 with availability 3 // there are 2 pieces with availability 2 and 5 with availability 3
print_title("test distributed copies");
p = setup_picker("1233333", "* ", "", ""); p = setup_picker("1233333", "* ", "", "");
float dc = p->distributed_copies(); float dc = p->distributed_copies();
TEST_CHECK(fabs(dc - (2.f + 5.f / 7.f)) < 0.01f); TEST_CHECK(fabs(dc - (2.f + 5.f / 7.f)) < 0.01f);
@ -216,6 +225,7 @@ int test_main()
// ======================================================== // ========================================================
// make sure filtered pieces are ignored // make sure filtered pieces are ignored
print_title("test filtered pieces");
p = setup_picker("1111111", " ", "0010000", ""); p = setup_picker("1111111", " ", "0010000", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("*** ** "), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector); p->pick_pieces(string2vec("*** ** "), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
@ -223,9 +233,23 @@ int test_main()
TEST_CHECK(int(picked.size()) > 0); TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front().piece_index == 2); TEST_CHECK(picked.front().piece_index == 2);
// ========================================================
// make sure we_dont_have works
print_title("test we_dont_have");
p = setup_picker("1111111", "*******", "0100000", "");
picked.clear();
p->we_dont_have(1);
p->we_dont_have(2);
p->pick_pieces(string2vec("*** ** "), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
TEST_CHECK(verify_pick(p, picked));
TEST_CHECK(int(picked.size()) > 0);
TEST_CHECK(picked.front().piece_index == 1);
// ======================================================== // ========================================================
// make sure requested blocks aren't picked // make sure requested blocks aren't picked
print_title("test don't pick requested blocks");
p = setup_picker("1234567", " ", "", ""); p = setup_picker("1234567", " ", "", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("*******"), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector); p->pick_pieces(string2vec("*******"), picked, 1, false, 0, piece_picker::fast, true, false, empty_vector);
@ -294,6 +318,7 @@ int test_main()
// ======================================================== // ========================================================
// test piece priorities // test piece priorities
print_title("test piece priorities");
p = setup_picker("5555555", " ", "3214576", ""); p = setup_picker("5555555", " ", "3214576", "");
TEST_CHECK(p->num_filtered() == 0); TEST_CHECK(p->num_filtered() == 0);
TEST_CHECK(p->num_have_filtered() == 0); TEST_CHECK(p->num_have_filtered() == 0);
@ -327,6 +352,7 @@ int test_main()
// ======================================================== // ========================================================
// test restore_piece // test restore_piece
print_title("test restore piece");
p = setup_picker("1234567", " ", "", ""); p = setup_picker("1234567", " ", "", "");
p->mark_as_finished(piece_block(0,0), 0); p->mark_as_finished(piece_block(0,0), 0);
p->mark_as_finished(piece_block(0,1), 0); p->mark_as_finished(piece_block(0,1), 0);
@ -380,6 +406,7 @@ int test_main()
// ======================================================== // ========================================================
// test non-rarest-first mode // test non-rarest-first mode
print_title("test not rarest first");
p = setup_picker("1234567", "* * * ", "1111122", ""); p = setup_picker("1234567", "* * * ", "1111122", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("****** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, false, false, empty_vector); p->pick_pieces(string2vec("****** "), picked, 5 * blocks_per_piece, false, 0, piece_picker::fast, false, false, empty_vector);
@ -397,6 +424,7 @@ int test_main()
// ======================================================== // ========================================================
// test have_all and have_none // test have_all and have_none
print_title("test have_all and have_none");
p = setup_picker("0123333", "* ", "", ""); p = setup_picker("0123333", "* ", "", "");
dc = p->distributed_copies(); dc = p->distributed_copies();
std::cout << "distributed copies: " << dc << std::endl; std::cout << "distributed copies: " << dc << std::endl;
@ -413,6 +441,7 @@ int test_main()
// ======================================================== // ========================================================
// test inc_ref and dec_ref // test inc_ref and dec_ref
print_title("test inc_ref dec_ref");
p = setup_picker("1233333", " * ", "", ""); p = setup_picker("1233333", " * ", "", "");
TEST_CHECK(test_pick(p) == 0); TEST_CHECK(test_pick(p) == 0);
@ -464,6 +493,7 @@ int test_main()
// ======================================================== // ========================================================
// test unverified_blocks, marking blocks and get_downloader // test unverified_blocks, marking blocks and get_downloader
print_title("test unverified blocks");
p = setup_picker("1111111", " ", "", "0300700"); p = setup_picker("1111111", " ", "", "0300700");
TEST_CHECK(p->unverified_blocks() == 2 + 3); TEST_CHECK(p->unverified_blocks() == 2 + 3);
TEST_CHECK(p->get_downloader(piece_block(4, 0)) == 0); TEST_CHECK(p->get_downloader(piece_block(4, 0)) == 0);
@ -503,6 +533,7 @@ int test_main()
// ======================================================== // ========================================================
// test prefer_whole_pieces // test prefer_whole_pieces
print_title("test prefer whole pieces");
p = setup_picker("1111111", " ", "", ""); p = setup_picker("1111111", " ", "", "");
picked.clear(); picked.clear();
p->pick_pieces(string2vec("*******"), picked, 1, 3, 0, piece_picker::fast, true, false, empty_vector); p->pick_pieces(string2vec("*******"), picked, 1, 3, 0, piece_picker::fast, true, false, empty_vector);
@ -533,6 +564,7 @@ int test_main()
// ======================================================== // ========================================================
// test parole mode // test parole mode
print_title("test parole mode");
p = setup_picker("3333133", " ", "", ""); p = setup_picker("3333133", " ", "", "");
p->mark_as_finished(piece_block(0, 0), 0); p->mark_as_finished(piece_block(0, 0), 0);
picked.clear(); picked.clear();
@ -561,6 +593,7 @@ int test_main()
// ======================================================== // ========================================================
// test suggested pieces // test suggested pieces
print_title("test suggested pieces");
p = setup_picker("1111222233334444", " ", "", ""); p = setup_picker("1111222233334444", " ", "", "");
int v[] = {1, 5}; int v[] = {1, 5};
std::vector<int> suggested_pieces(v, v + 2); std::vector<int> suggested_pieces(v, v + 2);