📄 downloader.py
字号:
self.all_requests = []
self.storage.reset_endgame()
def add_disconnected_seed(self, id):
# if not self.disconnectedseeds.has_key(id):
# self.picker.seed_seen_recently()
self.disconnectedseeds[id]=time()
# def expire_disconnected_seeds(self):
def num_disconnected_seeds(self):
# first expire old ones
expired = []
for id,t in self.disconnectedseeds.items():
if time() - t > EXPIRE_TIME: #Expire old seeds after so long
expired.append(id)
for id in expired:
# self.picker.seed_disappeared()
del self.disconnectedseeds[id]
return len(self.disconnectedseeds)
# if this isn't called by a stats-gathering function
# it should be scheduled to run every minute or two.
class DummyPicker:
def __init__(self, num, r):
self.stuff = range(num)
self.r = r
def next(self, wantfunc):
for i in self.stuff:
if wantfunc(i):
return i
return None
def lost_have(self, pos):
self.r.append('lost have')
def got_have(self, pos):
self.r.append('got have')
def requested(self, pos):
self.r.append('requested')
def complete(self, pos):
self.stuff.remove(pos)
self.r.append('complete')
def am_I_complete(self):
return false
class DummyStorage:
def __init__(self, remaining, have_endgame = false, numpieces = 1):
self.remaining = remaining
self.active = [[] for i in xrange(numpieces)]
self.endgame = false
self.have_endgame = have_endgame
def do_I_have_requests(self, index):
return self.remaining[index] != []
def request_lost(self, index, begin, length):
x = (begin, length)
self.active[index].remove(x)
self.remaining[index].append(x)
self.remaining[index].sort()
def piece_came_in(self, index, begin, piece):
self.active[index].remove((begin, len(piece)))
return true
def do_I_have(self, index):
return (self.remaining[index] == [] and
self.active[index] == [])
def new_request(self, index):
x = self.remaining[index].pop()
for i in self.remaining:
if i:
break
else:
self.endgame = true
self.active[index].append(x)
self.active[index].sort()
return x
def is_endgame(self):
return self.have_endgame and self.endgame
class DummyConnection:
def __init__(self, events):
self.events = events
def send_interested(self):
self.events.append('interested')
def send_not_interested(self):
self.events.append('not interested')
def send_request(self, index, begin, length):
self.events.append(('request', index, begin, length))
def send_cancel(self, index, begin, length):
self.events.append(('cancel', index, begin, length))
def test_stops_at_backlog():
ds = DummyStorage([[(0, 2), (2, 2), (4, 2), (6, 2)]])
events = []
d = Downloader(ds, DummyPicker(len(ds.remaining), events), 2, 15, 1, Measure(15), 10)
sd = d.make_download(DummyConnection(events))
assert events == []
assert ds.remaining == [[(0, 2), (2, 2), (4, 2), (6, 2)]]
assert ds.active == [[]]
sd.got_have_bitfield([true])
assert events == ['got have', 'interested']
del events[:]
assert ds.remaining == [[(0, 2), (2, 2), (4, 2), (6, 2)]]
assert ds.active == [[]]
sd.got_unchoke()
assert events == ['requested', ('request', 0, 6, 2), 'requested', ('request', 0, 4, 2)]
del events[:]
assert ds.remaining == [[(0, 2), (2, 2)]]
assert ds.active == [[(4, 2), (6, 2)]]
sd.got_piece(0, 4, 'ab')
assert events == ['requested', ('request', 0, 2, 2)]
del events[:]
assert ds.remaining == [[(0, 2)]]
assert ds.active == [[(2, 2), (6, 2)]]
def test_got_have_single():
ds = DummyStorage([[(0, 2)]])
events = []
d = Downloader(ds, DummyPicker(len(ds.remaining), events), 2, 15, 1, Measure(15), 10)
sd = d.make_download(DummyConnection(events))
assert events == []
assert ds.remaining == [[(0, 2)]]
assert ds.active == [[]]
sd.got_unchoke()
assert events == []
assert ds.remaining == [[(0, 2)]]
assert ds.active == [[]]
sd.got_have(0)
assert events == ['got have', 'interested', 'requested', ('request', 0, 0, 2)]
del events[:]
assert ds.remaining == [[]]
assert ds.active == [[(0, 2)]]
sd.disconnected()
assert events == ['lost have']
def test_choke_clears_active():
ds = DummyStorage([[(0, 2)]])
events = []
d = Downloader(ds, DummyPicker(len(ds.remaining), events), 2, 15, 1, Measure(15), 10)
sd1 = d.make_download(DummyConnection(events))
sd2 = d.make_download(DummyConnection(events))
assert events == []
assert ds.remaining == [[(0, 2)]]
assert ds.active == [[]]
sd1.got_unchoke()
sd1.got_have(0)
assert events == ['got have', 'interested', 'requested', ('request', 0, 0, 2)]
del events[:]
assert ds.remaining == [[]]
assert ds.active == [[(0, 2)]]
sd2.got_unchoke()
sd2.got_have(0)
assert events == ['got have']
del events[:]
assert ds.remaining == [[]]
assert ds.active == [[(0, 2)]]
sd1.got_choke()
assert events == ['interested', 'requested', ('request', 0, 0, 2), 'not interested']
del events[:]
assert ds.remaining == [[]]
assert ds.active == [[(0, 2)]]
sd2.got_piece(0, 0, 'ab')
assert events == ['complete', 'not interested']
del events[:]
assert ds.remaining == [[]]
assert ds.active == [[]]
def test_endgame():
ds = DummyStorage([[(0, 2)], [(0, 2)], [(0, 2)]], true, 3)
events = []
d = Downloader(ds, DummyPicker(len(ds.remaining), events), 10, 15, 3, Measure(15), 10)
ev1 = []
ev2 = []
ev3 = []
ev4 = []
sd1 = d.make_download(DummyConnection(ev1))
sd2 = d.make_download(DummyConnection(ev2))
sd3 = d.make_download(DummyConnection(ev3))
sd1.got_unchoke()
sd1.got_have(0)
assert ev1 == ['interested', ('request', 0, 0, 2)]
del ev1[:]
sd2.got_unchoke()
sd2.got_have(0)
sd2.got_have(1)
assert ev2 == ['interested', ('request', 1, 0, 2)]
del ev2[:]
sd3.got_unchoke()
sd3.got_have(0)
sd3.got_have(1)
sd3.got_have(2)
assert (ev3 == ['interested', ('request', 2, 0, 2), ('request', 0, 0, 2), ('request', 1, 0, 2)] or
ev3 == ['interested', ('request', 2, 0, 2), ('request', 1, 0, 2), ('request', 0, 0, 2)])
del ev3[:]
assert ev2 == [('request', 0, 0, 2)]
del ev2[:]
sd2.got_piece(0, 0, 'ab')
assert ev1 == [('cancel', 0, 0, 2), 'not interested']
del ev1[:]
assert ev2 == []
assert ev3 == [('cancel', 0, 0, 2)]
del ev3[:]
sd3.got_choke()
assert ev1 == []
assert ev2 == []
assert ev3 == []
sd3.got_unchoke()
assert (ev3 == [('request', 2, 0, 2), ('request', 1, 0, 2)] or
ev3 == [('request', 1, 0, 2), ('request', 2, 0, 2)])
del ev3[:]
assert ev1 == []
assert ev2 == []
sd4 = d.make_download(DummyConnection(ev4))
sd4.got_have_bitfield([true, true, true])
assert ev4 == ['interested']
del ev4[:]
sd4.got_unchoke()
assert (ev4 == [('request', 2, 0, 2), ('request', 1, 0, 2)] or
ev4 == [('request', 1, 0, 2), ('request', 2, 0, 2)])
assert ev1 == []
assert ev2 == []
assert ev3 == []
def test_stops_at_backlog_endgame():
ds = DummyStorage([[(2, 2), (0, 2)], [(2, 2), (0, 2)], [(0, 2)]], true, 3)
events = []
d = Downloader(ds, DummyPicker(len(ds.remaining), events), 3, 15, 3, Measure(15), 10)
ev1 = []
ev2 = []
ev3 = []
sd1 = d.make_download(DummyConnection(ev1))
sd2 = d.make_download(DummyConnection(ev2))
sd3 = d.make_download(DummyConnection(ev3))
sd1.got_unchoke()
sd1.got_have(0)
assert ev1 == ['interested', ('request', 0, 0, 2), ('request', 0, 2, 2)]
del ev1[:]
sd2.got_unchoke()
sd2.got_have(0)
assert ev2 == []
sd2.got_have(1)
assert ev2 == ['interested', ('request', 1, 0, 2), ('request', 1, 2, 2)]
del ev2[:]
sd3.got_unchoke()
sd3.got_have(2)
assert (ev2 == [('request', 0, 0, 2)] or
ev2 == [('request', 0, 2, 2)])
n = ev2[0][2]
del ev2[:]
sd1.got_piece(0, n, 'ab')
assert ev1 == []
assert ev2 == [('cancel', 0, n, 2), ('request', 0, 2-n, 2)]
# test piece flunking behavior
# make backlog of 1, one piece with two subpieces
# first connects, requests and gets part 1, requests part 2
# second connects, does nothing
# first gets part 2, flunks check, first requests part 1 and second requests part 2
# test piece flunking behavior endgame
# one piece, two sub-pieces, two peers
# second sub-piece comes in, assert gets request for both sub-pieces from both peers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -