diff -rN -u old-tahoe/src/allmydata/immutable/download.py new-tahoe/src/allmydata/immutable/download.py --- old-tahoe/src/allmydata/immutable/download.py 2010-02-01 05:40:57.643000000 +0000 +++ new-tahoe/src/allmydata/immutable/download.py 2010-02-01 05:41:02.752000000 +0000 @@ -343,12 +343,14 @@ the root hash (the number-0 hash), using the share_root_hash from the UEB""" precondition(share_hash_tree[0] is not None, share_hash_tree) + #precondition(isinstance(bucket, layout.ReadBucketProxy), bucket) prefix = "%d-%s-%s" % (sharenum, bucket, base32.b2a_l(share_hash_tree[0][:8], 60)) log.PrefixingLogMixin.__init__(self, facility="tahoe.immutable.download", prefix=prefix) self.sharenum = sharenum + #assert not isinstance(bucket, int) self.bucket = bucket self.share_hash_tree = share_hash_tree self.num_blocks = num_blocks diff -rN -u old-tahoe/src/allmydata/test/no_network.py new-tahoe/src/allmydata/test/no_network.py --- old-tahoe/src/allmydata/test/no_network.py 2010-02-01 05:40:58.420000000 +0000 +++ new-tahoe/src/allmydata/test/no_network.py 2010-02-01 05:41:03.631000000 +0000 @@ -37,7 +37,7 @@ class LocalWrapper: def __init__(self, original): self.original = original - self.broken = False + self.pre_call_notifier = None self.hung_until = None self.post_call_notifier = None self.disconnectors = {} @@ -64,8 +64,8 @@ return meth(*args, **kwargs) def _call(): - if self.broken: - raise IntentionalError("I was asked to break") + if self.pre_call_notifier: + self.pre_call_notifier() if self.hung_until: d2 = defer.Deferred() self.hung_until.addCallback(lambda ign: _really_call()) @@ -253,13 +253,18 @@ def break_server(self, serverid): # mark the given server as broken, so it will throw exceptions when # asked to hold a share or serve a share - self.servers_by_id[serverid].broken = True + def _break(ign): + raise IntentionalError("I was asked to break") + self.servers_by_id[serverid].pre_call_notifier = _break - def hang_server(self, serverid, until=defer.Deferred()): + def set_server_pre_call_notifier(self, serverid, cb): + self.servers_by_id[serverid].pre_call_notifier = cb + + def hang_server(self, serverid): # hang the given server ss = self.servers_by_id[serverid] assert ss.hung_until is None - ss.hung_until = until + ss.hung_until = defer.Deferred() def unhang_server(self, serverid): # unhang the given server diff -rN -u old-tahoe/src/allmydata/test/test_hung_server.py new-tahoe/src/allmydata/test/test_hung_server.py --- old-tahoe/src/allmydata/test/test_hung_server.py 2010-02-01 05:40:58.604000000 +0000 +++ new-tahoe/src/allmydata/test/test_hung_server.py 2010-02-01 05:41:03.825000000 +0000 @@ -1,7 +1,7 @@ import os, shutil from twisted.trial import unittest -from twisted.internet import defer +from twisted.internet import defer, reactor from allmydata import uri from allmydata.util.consumer import download_to_data from allmydata.immutable import upload @@ -21,6 +21,10 @@ for (id, ss) in servers: self.g.break_server(id) + def _notify(self, servers, cb): + for (id, ss) in servers: + self.g.set_server_pre_call_notifier(id, cb) + def _hang(self, servers, **kwargs): for (id, ss) in servers: self.g.hang_server(id, **kwargs) @@ -209,9 +213,10 @@ d = defer.succeed(None) for mutable in [False]: d.addCallback(lambda ign: self._set_up(mutable, "test_2_good_8_hung_then_1_recovers")) - d.addCallback(lambda ign: self._hang(self.servers[2:3])) - d.addCallback(lambda ign: self._hang(self.servers[3:])) - d.addCallback(lambda ign: self._unhang(self.servers[2:3])) + d.addCallback(lambda ign: self._hang(self.servers[2:])) + def _recover(): + self._unhang(self.servers[2:3]) + d.addCallback(lambda ign: reactor.callLater(5, _recover)) d.addCallback(lambda ign: self._download_and_check()) return d @@ -220,10 +225,29 @@ for mutable in [False]: d.addCallback(lambda ign: self._set_up(mutable, "test_2_good_8_hung_then_1_recovers_with_2_shares")) d.addCallback(lambda ign: self._copy_all_shares_from(self.servers[0:1], self.servers[2])) - d.addCallback(lambda ign: self._hang(self.servers[2:3])) - d.addCallback(lambda ign: self._hang(self.servers[3:])) - d.addCallback(lambda ign: self._unhang(self.servers[2:3])) + d.addCallback(lambda ign: self._hang(self.servers[2:])) + def _recover(): + self._unhang(self.servers[2:3]) + d.addCallback(lambda ign: reactor.callLater(5, _recover)) + d.addCallback(lambda ign: self._download_and_check()) + return d + + def test_use_first_servers_to_reply(self): + d = defer.succeed(None) + count = 0 # servers after the first two that receive requests + for mutable in [False]: + d.addCallback(lambda ign: self._set_up(mutable, "test_use_first_servers_to_reply")) + def _incr_count(): + count += 1 + d.addCallback(lambda ign: self._notify(self.servers[2:], _incr_count)) + d.addCallback(lambda ign: self._hang(self.servers[2:])) + def _recover(): + self._unhang(self.servers[2:]) + d.addCallback(lambda ign: reactor.callLater(5, _recover)) d.addCallback(lambda ign: self._download_and_check()) + def _check_count(ign): + self.failUnlessEqual(count, 1) + d.addCallback(_check_count) return d def test_failover_during_stage_4(self): @@ -240,5 +264,4 @@ doned.addCallback(self._check) return doned d.addCallback(_after_starting_download) - return d