def __init__(self, mode):
self.mode = mode
self.allocated = []
+ self.queries = 0
def callRemote(self, methname, *args, **kwargs):
def _call():
meth = getattr(self, methname)
def allocate_buckets(self, storage_index, renew_secret, cancel_secret,
sharenums, share_size, canary):
#print "FakeStorageServer.allocate_buckets(num=%d, size=%d)" % (len(sharenums), share_size)
+ self.queries += 1
if self.mode == "full":
return (set(), {},)
elif self.mode == "already got them":
for p in self.node.last_peers:
allocated = p.ss.allocated
self.failUnlessEqual(len(allocated), 1)
+ self.failUnlessEqual(p.ss.queries, 1)
d.addCallback(_check)
return d
for p in self.node.last_peers:
allocated = p.ss.allocated
self.failUnlessEqual(len(allocated), 2)
+ self.failUnlessEqual(p.ss.queries, 2)
d.addCallback(_check)
return d
allocated = p.ss.allocated
self.failUnless(len(allocated) in (1,2), len(allocated))
if len(allocated) == 1:
+ self.failUnlessEqual(p.ss.queries, 1)
got_one.append(p)
else:
+ self.failUnlessEqual(p.ss.queries, 2)
got_two.append(p)
self.failUnlessEqual(len(got_one), 49)
self.failUnlessEqual(len(got_two), 1)
d.addCallback(_check)
return d
+ def test_four_each(self):
+ # if we have 200 shares, and there are 50 peers, then each peer gets
+ # 4 shares. The design goal is to accomplish this with only two
+ # queries per peer.
+
+ data = self.get_data(SIZE_LARGE)
+ self.u.DEFAULT_ENCODING_PARAMETERS = (100, 150, 200)
+ d = self.u.upload_data(data)
+ d.addCallback(self._check_large, SIZE_LARGE)
+ def _check(res):
+ for p in self.node.last_peers:
+ allocated = p.ss.allocated
+ self.failUnlessEqual(len(allocated), 4)
+ self.failUnlessEqual(p.ss.queries, 2)
+ d.addCallback(_check)
+ return d
+
# TODO:
# upload with exactly 75 peers (shares_of_happiness)
self.homeless_shares = range(total_shares)
# self.uncontacted_peers = list() # peers we haven't asked yet
- self.contacted_peers = list() # peers worth asking again
+ self.contacted_peers = ["start"] # peers worth asking again
self.use_peers = set() # PeerTrackers that have shares assigned to them
self.preexisting_shares = {} # sharenum -> PeerTracker holding the share
d = peer.query(shares_to_ask)
d.addBoth(self._got_response, peer, shares_to_ask)
return d
- elif self.contacted_peers:
+ elif len(self.contacted_peers) > 1:
# ask a peer that we've already asked.
- num_shares = mathutil.div_ceil(len(self.homeless_shares),
- len(self.contacted_peers))
- shares_to_ask = set(self.homeless_shares[:num_shares])
- self.homeless_shares[:num_shares] = []
peer = self.contacted_peers.pop(0)
+ if peer == "start":
+ # we're at the beginning of the list, so re-calculate
+ # shares_per_peer
+ num_shares = mathutil.div_ceil(len(self.homeless_shares),
+ len(self.contacted_peers))
+ self.shares_per_peer = num_shares
+ self.contacted_peers.append("start")
+ peer = self.contacted_peers.pop(0)
+ shares_to_ask = set(self.homeless_shares[:self.shares_per_peer])
+ self.homeless_shares[:self.shares_per_peer] = []
self.query_count += 1
d = peer.query(shares_to_ask)
d.addBoth(self._got_response, peer, shares_to_ask)
log.msg("%s got error during peer selection: %s" % (peer, res))
self.error_count += 1
self.homeless_shares = list(shares_to_ask) + self.homeless_shares
- if self.uncontacted_peers or self.contacted_peers:
+ if self.uncontacted_peers or len(self.contacted_peers) > 1:
# there is still hope, so just loop
pass
else: