📄 download.py
字号:
self.multidownload.all_requests = set() for d in self.multidownload.downloads: self.multidownload.all_requests.update(d.active_requests) for d in self.multidownload.downloads: d.fix_download_endgame() def _check_lost_interests(self, lost_interests): """ Notify other downloads that these pieces are no longer interesting. @param lost_interests: list of pieces that have been fully requested. """ if not lost_interests: return for d in self.multidownload.downloads: if d.active_requests or not d.interested: continue if d.example_interest is not None and not \ self.multidownload.storage.have[d.example_interest] and \ self.multidownload.storage.want_requests(d.example_interest): continue # any() does not exist until python 2.5 #if not any([d.have[lost] for lost in lost_interests]): # continue for lost in lost_interests: if d.have[lost]: break else: continue interest = self.multidownload.picker.from_behind(self.have, self.multidownload.storage.full_pieces) if interest is None: d.interested = False d.connection.send_not_interested() else: d.example_interest = interest def _request_when_choked(self): self.allowed_fast_pieces = [i for i in self.allowed_fast_pieces if not self.multidownload.storage.do_I_have(i)] if not self.allowed_fast_pieces: return fast = list(self.allowed_fast_pieces) b = self._backlog() lost_interests = [] while len(self.active_requests) < b: while fast: piece = fast.pop() if self.have[piece] \ and self.multidownload.storage.want_requests(piece): break else: break # no unrequested pieces among allowed fast. # request chunks until no more chunks or no more room in backlog. while len(self.active_requests) < b: begin, length = self.multidownload.storage.new_request(piece, self.prefer_full) self.multidownload.active_requests_add(piece) self.active_requests.add((piece, begin, length)) self.connection.send_request(piece, begin, length) if not self.multidownload.storage.want_requests(piece): lost_interests.append(piece) break self._check_lost_interests(lost_interests) if self.multidownload.storage.endgame: self.multidownload.all_requests = set() for d in self.multidownload.downloads: self.multidownload.all_requests.update(d.active_requests) for d in self.multidownload.downloads: d.fix_download_endgame() def fix_download_endgame(self): want = [] for a in self.multidownload.all_requests: if not self.have[a[0]]: continue if a in self.active_requests: continue want.append(a) if self.interested and not self.active_requests and not want: self.interested = False self.connection.send_not_interested() return if not self.interested and want: self.interested = True self.connection.send_interested() if self.choked: return random.shuffle(want) for req in want[:self._backlog() - len(self.active_requests)]: self.active_requests.add(req) self.connection.send_request(*req) def got_have(self, index): if self.have[index]: return if index == self.multidownload.numpieces-1: self.peermeasure.update_rate(self.multidownload.storage.total_length- (self.multidownload.numpieces-1)*self.multidownload.storage.piece_size) else: self.peermeasure.update_rate(self.multidownload.storage.piece_size) self.have[index] = True self.multidownload.got_have(index) if self.multidownload.storage.get_amount_left() == 0 and self.have.numfalse == 0: self.connection.close() return if self.multidownload.storage.endgame: self.fix_download_endgame() elif self.multidownload.storage.want_requests(index): self._request_more([index]) # call _request_more whether choked. if self.choked: if not self.interested: self.interested = True self.connection.send_interested() def got_have_bitfield(self, have): if have.numfalse == 0: self._got_have_all(have) return self.have = have # arg, slow count = 0 target = len(self.have) - self.have.numfalse for i in xrange(len(self.have)): if count == target: break if self.have[i]: self.multidownload.got_have(i) count += 1 if self.multidownload.storage.endgame: for piece, begin, length in self.multidownload.all_requests: if self.have[piece]: self.interested = True self.connection.send_interested() return for piece in self.multidownload.storage.iter_want(): if self.have[piece]: self.interested = True self.connection.send_interested() return def _got_have_all(self, have=None): if self.multidownload.storage.get_amount_left() == 0: self.connection.close() return if have is None: # bleh n = self.multidownload.numpieces rlen, extra = divmod(n, 8) if extra: extra = chr((0xFF << (8 - extra)) & 0xFF) else: extra = '' s = (chr(0xFF) * rlen) + extra have = Bitfield(n, s) self.have = have self.multidownload.got_have_all() if self.multidownload.storage.endgame: for piece, begin, length in self.multidownload.all_requests: self.interested = True self.connection.send_interested() return for i in self.multidownload.storage.iter_want(): self.interested = True self.connection.send_interested() return def update_rate(self, amount): self.measure.update_rate(amount) self.multidownload.update_rate(amount) def get_rate(self): return self.measure.get_rate() def is_snubbed(self): return bttime() - self.last > self.multidownload.snub_time def got_have_none(self): pass # currently no action is taken when have_none is received. # The picker already assumes the local peer has none of the # pieces until got_have is called. def got_have_all(self): assert self.connection.uses_fast_extension self._got_have_all() def got_suggest_piece(self, piece): assert self.connection.uses_fast_extension if not self.multidownload.storage.do_I_have(piece): self.suggested_pieces.append(piece) self._request_more() # try to request more. Just returns if choked. def got_allowed_fast(self,piece): """Upon receiving this message, the multidownload knows that it is allowed to download the specified piece even when choked.""" #log( "got_allowed_fast %d" % piece ) assert self.connection.uses_fast_extension if not self.multidownload.storage.do_I_have(piece): if piece not in self.allowed_fast_pieces: self.allowed_fast_pieces.append(piece) random.shuffle(self.allowed_fast_pieces) # O(n) but n is small. self._request_more() # will try to request. Handles cases like # whether neighbor has "allowed fast" piece. def got_reject_request(self, piece, begin, length): if not self.connection.uses_fast_extension: self.connection.close() return req = (piece, begin, length) if req not in self.active_requests: self.connection.close() return self.active_requests.remove(req) if self.multidownload.storage.endgame: return self.multidownload.storage.request_lost(*req) if not self.choked: self._request_more() ds = [d for d in self.multidownload.downloads if not d.choked] random.shuffle(ds) for d in ds: d._request_more([piece]) for d in self.multidownload.downloads: if d.choked and not d.interested: if d.have[piece] and \ self.multidownload.storage.want_requests(piece): d.interested = True d.connection.send_interested() break
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -