def uploads(self, requests, peers, history): """ requests -- a list of the requests for this peer for this round peers -- available info about all the peers history -- history for all previous rounds returns: list of Upload objects. In each round, this will be called after requests(). """ ################################################################## ########### updating d_js ######################################## ################################################################## alpha = 0.2 gamma = 0.1 round = history.current_round() self.bandwidthHistory.append(self.up_bw) if round == 0: for peer in peers: self.downloadRate[peer.id] = 1 self.uploadRate[peer.id] = 1 self.slots[peer.id] = 4 self.downloadUploadRatio[peer.id] = self.downloadRate[peer.id]/self.uploadRate[peer.id] else: for peer in peers: for download in history.downloads[round-1]: if peer.id == download.from_id: self.downloadRate[peer.id] = download.blocks if download.blocks == 0: print "!!!!!! %s uploaded %s block(s)" % (peer.id, download.blocks) self.slots[peer.id] = mean(self.bandwidthHistory)/float(self.downloadRate[peer.id]) # Find how to find out max and min bw or infer from personal history if round >= 3: peer_download = 0 for download2 in history.downloads[round-2]: if peer.id == download2.from_id: for download3 in history.downloads[round-3]: if peer.id == download3.from_id: peer_download += 1 if peer_download > 0: self.uploadRate[peer.id] *= 1 - gamma break if len(peer.available_pieces) > 0: av_pieces = float(len(peer.available_pieces)) rnd = float(round) slots = float(self.slots[peer.id]) self.downloadRate[peer.id] = av_pieces/(rnd * slots) #self.downloadRate[peer.id] = float((len(peer.available_pieces)/float(round)))/float(self.slots[peer.id]) self.uploadRate[peer.id] *= 1 + alpha if self.downloadRate[peer.id] == 0: print str(peer.id) + ": " + str(peer.available_pieces) print "Peer %s has %s available pieces" % (peer.id, len(peer.available_pieces)) print "downloadUploadRatio" print self.downloadUploadRatio ########### updating current ratio ############################### if round == 0: for peer in peers: self.downloadUploadRatio[peer.id] = 1 else: for peer in peers: self.downloadUploadRatio[peer.id] = self.downloadRate[peer.id]/self.uploadRate[peer.id] ################################################################### print "download rates" print self.downloadRate print "Upload rates" print self.uploadRate print "donwload upload ratio" print self.downloadUploadRatio print "slots" print self.slots logging.debug("%s again. It's round %d." % ( self.id, round)) # One could look at other stuff in the history too here. # For example, history.downloads[round-1] (if round != 0, of course) # has a list of Download objects for each Download to this peer in # the previous round. if len(requests) == 0: logging.debug("No one wants my pieces!") chosen = [] bws = [] uploads = [] else: logging.debug("Still here: uploading to a random peer") # change my internal state for no reason self.dummy_state["cake"] = "pie" ########### Building upload list ################################# sumUpload = 0 chosen = {} downloadUploadRatio_tmp = {} # creating list with ratios for only peers in requests for request in requests: downloadUploadRatio_tmp[request.requester_id] = self.downloadUploadRatio[request.requester_id] print self.downloadUploadRatio[request.requester_id] while (sumUpload <= len(peers) and len(downloadUploadRatio_tmp) > 0): peer_id = max(downloadUploadRatio_tmp, key = downloadUploadRatio_tmp.get) chosen[peer_id] = downloadUploadRatio_tmp.pop(peer_id) sumUpload += self.uploadRate[peer_id] # print "sumUpload of %s" % (peer_id) # print sumUpload # print downloadUploadRatio_tmp[peer_id] # print self.uploadRate[peer_id] """ Calculate the total proportional BW allocated to other peers """ totalUploadBW = 0 for choice in chosen: totalUploadBW += chosen[choice] # print chosen[choice] """ Make each BW as a proportion of totalUploadBW """ for choice in chosen: chosen[choice] = 100 * float(chosen[choice]) / float(totalUploadBW) # print "Vector of choices for this round:" # print chosen """ Now need to divide our BW as integers according to chosen vector """ peerWeights = [value for (key, value) in sorted(chosen.items())] peerNames = sorted(chosen) # print "original chosen: %s" % (chosen) # print "names: %s" % (peerNames) # print "weights: %s" % (peerWeights) # request = random.choice(requests) # chosen = [request.requester_id] # Evenly "split" my upload bandwidth among the one chosen requester # bws = even_split(self.up_bw, len(chosen)) bws = proportional_split(self.up_bw, peerWeights) # create actual uploads out of the list of peer ids and bandwidths uploads = [Upload(self.id, peer_id, bw) for (peer_id, bw) in zip(chosen, bws)] return uploads
def uploads(self, requests, peers, history): """ requests -- a list of the requests for this peer for this round peers -- available info about all the peers history -- history for all previous rounds returns: list of Upload objects. In each round, this will be called after requests(). """ ################################################################## ########### updating d_js ######################################## ################################################################## alpha = 0.2 gamma = 0.1 round = history.current_round() self.bandwidthHistory.append(self.up_bw) if round == 0: bw_list = even_split(self.up_bw,len(peers)) for peer,i in zip(peers,range(len(peers))): self.downloadRate[peer.id] = 1 if bw_list[i] == 0: self.uploadRate[peer.id] = 0.5 else: self.uploadRate[peer.id] = bw_list[i] self.slots[peer.id] = 4 self.downloadUploadRatio[peer.id] = 1 else: for peer in peers: for download in history.downloads[round-1]: if peer.id == download.from_id: self.downloadRate[peer.id] = download.blocks if download.blocks == 0: print "!!!!!! %s uploaded %s block(s)" % (peer.id, download.blocks) self.slots[peer.id] = mean(self.bandwidthHistory)/float(self.downloadRate[peer.id]) # Find how to find out max and min bw or infer from personal history if round >= 3: peer_download = 0 for download2 in history.downloads[round-2]: if peer.id == download2.from_id: for download3 in history.downloads[round-3]: if peer.id == download3.from_id: peer_download += 1 if peer_download > 0: self.uploadRate[peer.id] *= 1 - gamma break if len(peer.available_pieces) > 0: av_pieces = float(len(peer.available_pieces)) rnd = float(round) slots = float(self.slots[peer.id]) self.downloadRate[peer.id] = av_pieces/(rnd * self.conf.blocks_per_piece * slots) self.uploadRate[peer.id] *= 1 + alpha #if self.downloadRate[peer.id] == 0: # print str(peer.id) + ": " + str(peer.available_pieces) # print "Peer %s has %s available pieces" % (peer.id, len(peer.available_pieces)) self.downloadUploadRatio[peer.id] = self.downloadRate[peer.id]/self.uploadRate[peer.id] logging.debug("%s again. It's round %d." % ( self.id, round)) ########### Dynamic Optimistic Unchoking ################################# ########### Eallocate each 3 rounds ###################################### ### Choose peer to uchoke every 3 round ### Choose # of peers divided by x: x = 3 if round % 3 ==0: self.optUnchokedPeers = random.sample(peers, len(peers)/x) ### Initial share to uchoke: a = 0.5 availPiecesShare = float(sum(self.pieces))/float(self.conf.num_pieces*self.conf.blocks_per_piece) ### Allocate BW to opt unchoking bwToOptUnchoking = (a*self.up_bw - availPiecesShare * self.up_bw * a) + 0.001 ### Divide this BW among number of neighbors divided by x bwToOptUnchoking = bwToOptUnchoking/(len(peers)/x) optUnchokedAllocation = {} for peer in self.optUnchokedPeers: optUnchokedAllocation[peer.id] = float(100 * bwToOptUnchoking) /(float((a*self.up_bw - availPiecesShare * self.up_bw * a)) +0.001) up_bw_available = self.up_bw - bwToOptUnchoking*(len(peers)/x) # Removing optimistically unchoked peers from consideration peers_tmp = list(peers) for peer in self.optUnchokedPeers: if peer in peers_tmp: peers_tmp.remove(peer) ######################################################################### ########### Building upload list ######################################## ######################################################################### if len(requests) == 0: logging.debug("No one wants my pieces!") chosen = [] bws = [] uploads = [] else: sumUpload = 0 chosen = {} downloadUploadRatio_tmp = {} # creating list with ratios for only peers in requests for request in requests: for peer in peers_tmp: if request.requester_id == peer.id: downloadUploadRatio_tmp[request.requester_id] = self.downloadUploadRatio[request.requester_id] for key in downloadUploadRatio_tmp: if downloadUploadRatio_tmp[key] in self.optUnchokedPeers: downloadUploadRatio_tmp.pop(key) needed = lambda i: self.pieces[i] < self.conf.blocks_per_piece needed_pieces = filter(needed, range(len(self.pieces))) while (sumUpload <= up_bw_available * 0.75 and len(downloadUploadRatio_tmp) > 0): peer_id = max(downloadUploadRatio_tmp, key = downloadUploadRatio_tmp.get) chosen[peer_id] = downloadUploadRatio_tmp.pop(peer_id) sumUpload += self.uploadRate[peer_id] """ Calculate the total proportional BW allocated to other peers """ totalUploadBW = 0 for choice in chosen: totalUploadBW += chosen[choice] """ Make each BW as a proportion of totalUploadBW """ if (float(totalUploadBW) * len(optUnchokedAllocation) == 0): uploads = [] else: for choice in chosen: chosen[choice] = 100 * float(chosen[choice]) / float(totalUploadBW) ### Connecting optimistic unchoking list to tyrant list # chosen.update(optUnchokedAllocation) # print "Vector of choices for this round:" # print chosen """ Now need to divide our BW as integers according to chosen vector """ peerWeights = [value for (key, value) in sorted(chosen.items())] peerNames = sorted(chosen) # print "original chosen: %s" % (chosen) # print "names: %s" % (peerNames) # print "weights: %s" % (peerWeights) bws = proportional_split(int(math.floor(up_bw_available)), peerWeights) # create actual uploads out of the list of peer ids and bandwidths uploads = [Upload(self.id, peer_id, bw) for (peer_id, bw) in zip(chosen, bws)] peerWeights = [value for (key, value) in sorted(optUnchokedAllocation.items())] peerNames = sorted(optUnchokedAllocation) bws = proportional_split(self.up_bw - int(up_bw_available), peerWeights) uploads2 = [Upload(self.id, peer_id, bw) for (peer_id, bw) in zip(peerNames, bws)] uploads = uploads + uploads2 if (round + 1) % 5 == 0: request = random.choice(requests) chosen = [request.requester_id] # Evenly "split" my upload bandwidth among the one chosen requester bws = even_split(self.up_bw, len(chosen)) #uploads = uploads.append([Upload(self.id, peer_id, bw) # for (peer_id, bw) in zip(optUnchokedAllocation, bws)]) return uploads