00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef TORRENT_PIECE_PICKER_HPP_INCLUDED
00033 #define TORRENT_PIECE_PICKER_HPP_INCLUDED
00034
00035 #include <algorithm>
00036 #include <vector>
00037 #include <bitset>
00038 #include <cassert>
00039
00040 #ifdef _MSC_VER
00041 #pragma warning(push, 1)
00042 #endif
00043
00044 #include <boost/optional.hpp>
00045
00046 #ifdef _MSC_VER
00047 #pragma warning(pop)
00048 #endif
00049
00050 #include "libtorrent/peer_id.hpp"
00051 #include "libtorrent/socket.hpp"
00052 #include "libtorrent/session_settings.hpp"
00053 #include "libtorrent/config.hpp"
00054
00055 namespace libtorrent
00056 {
00057
00058 class torrent;
00059 class peer_connection;
00060
00061 struct TORRENT_EXPORT piece_block
00062 {
00063 piece_block(int p_index, int b_index)
00064 : piece_index(p_index)
00065 , block_index(b_index)
00066 {}
00067 int piece_index;
00068 int block_index;
00069
00070 bool operator<(piece_block const& b) const
00071 {
00072 if (piece_index < b.piece_index) return true;
00073 if (piece_index == b.piece_index) return block_index < b.block_index;
00074 return false;
00075 }
00076
00077 bool operator==(piece_block const& b) const
00078 { return piece_index == b.piece_index && block_index == b.block_index; }
00079
00080 bool operator!=(piece_block const& b) const
00081 { return piece_index != b.piece_index || block_index != b.block_index; }
00082
00083 };
00084
00085 class TORRENT_EXPORT piece_picker
00086 {
00087 public:
00088
00089 enum { max_blocks_per_piece = 256 };
00090
00091 struct block_info
00092 {
00093 block_info(): num_downloads(0) {}
00094
00095
00096 tcp::endpoint peer;
00097
00098 int num_downloads;
00099 };
00100
00101 struct downloading_piece
00102 {
00103 int index;
00104
00105
00106 std::bitset<max_blocks_per_piece> requested_blocks;
00107
00108 std::bitset<max_blocks_per_piece> finished_blocks;
00109
00110 block_info info[max_blocks_per_piece];
00111 };
00112
00113 piece_picker(int blocks_per_piece
00114 , int total_num_blocks);
00115
00116 void set_sequenced_download_threshold(int sequenced_download_threshold);
00117
00118
00119
00120
00121
00122 void files_checked(
00123 const std::vector<bool>& pieces
00124 , const std::vector<downloading_piece>& unfinished);
00125
00126
00127
00128 void inc_refcount(int index);
00129
00130
00131
00132 void dec_refcount(int index);
00133
00134
00135
00136
00137
00138 void we_have(int index);
00139
00140
00141
00142
00143
00144 void mark_as_unfiltered(int index);
00145
00146
00147
00148
00149 void mark_as_filtered(int index);
00150
00151
00152 bool is_filtered(int index) const;
00153
00154
00155 void filtered_pieces(std::vector<bool>& mask) const;
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 void pick_pieces(const std::vector<bool>& pieces
00169 , std::vector<piece_block>& interesting_blocks
00170 , int num_pieces, bool prefer_whole_pieces
00171 , tcp::endpoint peer) const;
00172
00173
00174
00175
00176 bool is_downloading(piece_block block) const;
00177 bool is_finished(piece_block block) const;
00178
00179
00180 void mark_as_downloading(piece_block block, tcp::endpoint const& peer);
00181 void mark_as_finished(piece_block block, tcp::endpoint const& peer);
00182
00183
00184
00185 void restore_piece(int index);
00186
00187
00188
00189 void abort_download(piece_block block);
00190
00191 bool is_piece_finished(int index) const;
00192
00193
00194 int blocks_in_piece(int index) const;
00195
00196
00197
00198 int unverified_blocks() const;
00199
00200 void get_downloaders(std::vector<tcp::endpoint>& d, int index) const;
00201
00202 std::vector<downloading_piece> const& get_download_queue() const
00203 { return m_downloads; }
00204
00205 boost::optional<tcp::endpoint> get_downloader(piece_block block) const;
00206
00207
00208 int num_filtered() const { return m_num_filtered; }
00209
00210
00211 int num_have_filtered() const { return m_num_have_filtered; }
00212 #ifndef NDEBUG
00213
00214 void check_invariant(const torrent* t = 0) const;
00215 #endif
00216
00217
00218 struct has_index
00219 {
00220 has_index(int i): index(i) { assert(i >= 0); }
00221 bool operator()(const downloading_piece& p) const
00222 { return p.index == index; }
00223 int index;
00224 };
00225
00226 int blocks_in_last_piece() const
00227 { return m_blocks_in_last_piece; }
00228
00229 float distributed_copies() const;
00230
00231 private:
00232
00233 struct piece_pos
00234 {
00235 piece_pos() {}
00236 piece_pos(int peer_count_, int index_)
00237 : peer_count(peer_count_)
00238 , downloading(0)
00239 , filtered(0)
00240 , index(index_)
00241 {
00242 assert(peer_count_ >= 0);
00243 assert(index_ >= 0);
00244 }
00245
00246
00247 unsigned peer_count : 11;
00248
00249 unsigned downloading : 1;
00250
00251 unsigned filtered : 1;
00252
00253 unsigned index : 19;
00254
00255 enum { we_have_index = 0x3ffff };
00256
00257 int priority(int limit) const
00258 {
00259 return peer_count >= (unsigned)limit ? limit : peer_count;
00260 }
00261
00262 bool ordered(int limit) const
00263 {
00264 return peer_count >= (unsigned)limit;
00265 }
00266
00267 bool operator!=(piece_pos p) const
00268 { return index != p.index || peer_count != p.peer_count; }
00269
00270 bool operator==(piece_pos p) const
00271 { return index == p.index && peer_count == p.peer_count; }
00272
00273 };
00274
00275
00276 void add(int index);
00277 void move(bool downloading, bool filtered, int vec_index, int elem_index);
00278 void remove(bool downloading, bool filtered, int vec_index, int elem_index);
00279 std::vector<std::vector<int> >& pick_piece_info_vector(bool downloading
00280 , bool filtered);
00281
00282 std::vector<std::vector<int> > const& pick_piece_info_vector(
00283 bool downloading, bool filtered) const;
00284
00285 int add_interesting_blocks_free(const std::vector<int>& piece_list
00286 , const std::vector<bool>& pieces
00287 , std::vector<piece_block>& interesting_blocks
00288 , int num_blocks, bool prefer_whole_pieces) const;
00289
00290 int add_interesting_blocks_partial(const std::vector<int>& piece_list
00291 , const std::vector<bool>& pieces
00292 , std::vector<piece_block>& interesting_blocks
00293 , std::vector<piece_block>& backup_blocks
00294 , int num_blocks, bool prefer_whole_pieces
00295 , tcp::endpoint peer) const;
00296
00297
00298
00299
00300
00301
00302
00303 std::vector<std::vector<int> > m_piece_info;
00304
00305
00306
00307
00308
00309 std::vector<std::vector<int> > m_downloading_piece_info;
00310
00311
00312
00313
00314
00315
00316
00317 std::vector<piece_pos> m_piece_map;
00318
00319
00320
00321
00322
00323 std::vector<downloading_piece> m_downloads;
00324
00325 int m_blocks_per_piece;
00326 int m_blocks_in_last_piece;
00327
00328
00329
00330
00331
00332 int m_num_filtered;
00333
00334
00335 int m_num_have_filtered;
00336
00337
00338
00339 int m_sequenced_download_threshold;
00340 #ifndef NDEBUG
00341 bool m_files_checked_called;
00342 #endif
00343 };
00344
00345 inline int piece_picker::blocks_in_piece(int index) const
00346 {
00347 assert(index >= 0);
00348 assert(index < (int)m_piece_map.size());
00349 if (index+1 == (int)m_piece_map.size())
00350 return m_blocks_in_last_piece;
00351 else
00352 return m_blocks_per_piece;
00353 }
00354
00355 }
00356
00357 #endif // TORRENT_PIECE_PICKER_HPP_INCLUDED
00358