Example #1
0
    def complete(self, event = None):
        filename = self.fileInfoPanel.dirCtl.GetValue()
        if filename == '':
            dlg = wx.MessageDialog(self, message = self.utility.lang.get('youmustselectfileordir'), 
                caption = self.utility.lang.get('error'), style = wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return
        
        params = self.fileInfoPanel.getParams()
        params = union(params, self.trackerInfoPanel.getParams())
        params = union(params, self.miscInfoPanel.getParams())

        try:
            CompleteDir(self, filename, params['announce'], params)
        except:
            oldstdout = sys.stdout
            sys.stdout = sys.stderr
            print_exc()
            sys.stdout = oldstdout
Example #2
0
    def CalculateBandwidth(self, dir = "up"):
        if dir == "up":
            workingset = union(self.utility.torrents["downloading"], self.utility.torrents["seeding"])
        else:
            workingset = self.utility.torrents["downloading"]

        # Limit working set to active torrents with connections:
        workingset = [torrent for torrent in workingset if torrent.status.isActive() and torrent.connection.engine.hasConnections]

        # No active file, not need to calculate
        if not workingset:
            return
        
        maxrate = self.MaxRate(dir)
        # See if global rate settings are set to unlimited
        if maxrate == 0:
            # Unlimited rate
            for torrent in workingset:
                torrent.connection.maxrate[dir] = torrent.connection.getLocalRate(dir)
                torrent.connection.setRate(torrent.connection.maxrate[dir], dir)
            return
        
        #print "====================== BEGINNING ALGO ======= th1=%.1f ; th2=%.1f =============================" % (self.calcupth1, self.calcupth2)

        #######################################################
        # - Find number of completed/incomplete torrent
        # - Number of torrent using local setting
        # - bandwidth already used by torrents
        # - Sorting of torrents in lists according to their will in matter of upload rate :
        #   (tobelowered, toberaisedinpriority, toberaised, nottobechanged)
        #######################################################

        # Option set in Preferences/Queue.
        # If not set, torrents with rate local settings are treated like other torrents, except they have their
        # own max rate they can't cross over. The consequence is a behaviour slightly different from the behavior of
        # ABC releases prior to 2.7.0.
        # If set, this gives the algorithm the behaviour of ABC releases prior to 2.7.0 : the torrents with an rate
        # local setting will be granted bandwidth in priority to fulfill their local setting, even is this one
        # is higher than the global max rate setting, and even if this bandwidth must be taken from other active
        # torrents wihout a local rate setting. These torrents will not take part in the rate exchange
        # between active torrents when all bandwidth has been distributed, since they will have been served in priority.
        prioritizelocal = self.utility.config.Read('prioritizelocal', "boolean")

        # torrents with local rate settings when prioritizelocal is set (see prioritizelocal)
        localprioactive = []       
    
        # torrents for which measured rate is lowering and so reserved rate can be lowered
        tobelowered = []
     
        # torrents for which measured rate is growing and so reserved rate can be raised,
        # (with reserved rate > 3 kB/s for uploading)
        toberaised  = []                           

        # torrents for which reserved rate can be raised, with reserved rate < 3 kB/s
        # These will always be raised even there's no available up bandwith, to fulfill the min 3 kB/s rate rule
        toberaisedinpriority = []                             

        # torrents for which reserved rate is not to be changed and is > rateminimum; (for these, the
        # measured rate is between (max upload reserved - calcupth1) and (max upload reserved - calcupth2)
        nottobechanged = []   

        meanrate = 0.0            # mean max rate for torrents to be raised or not to be changed ; it will be used to decide which torrents
                              # must be raised amongst those that want to get higher and that must share the available up bandwidth. The torrents
                              # that don't want to change their rate and that are below 3 kB/s are not taken into account on purpose, because
                              # these ones will never be lowered to give more rate to a torrent that wants to raise its rate, or to
                              # compensate for the rate given to torrents to be raised in priority.

        for torrent in workingset:
            # Active Torrent
            currentrate = torrent.connection.rate[dir]

            maxrate_float = torrent.connection.maxrate[dir]

            # Torrents dispatch
            if prioritizelocal and torrent.connection.getLocalRate(dir, True):
                localprioactive.append(torrent)
            elif currentrate < 0.05:
                # These are the torrents that don't want to have their rate changed and that have an allmost null rate
                # They will not go lower, we can reset their reserved rate until they want to get higher
                torrent.connection.maxrate[dir] = 0.0
            elif maxrate_float - currentrate > self.calcupth1:
                tobelowered.append(torrent)
            elif maxrate_float - currentrate <= self.calcupth2:
                if currentrate < self.rateminimum[dir]:
                    toberaisedinpriority.append(torrent)
                else:
                    toberaised.append(torrent)
                    meanrate += maxrate_float
            elif currentrate > self.rateminimum[dir]:
                nottobechanged.append(torrent)
                meanrate += maxrate_float

#        print "index: %i ; rate: %.1f ; reserved: %.1f ; maxlocal: %.1f" % (torrent.listindex, \
#              currentrate, maxrate_float, float(torrent.connection.maxlocalrate[dir]))

        ###############################################
        # Calculate rate for each torrent
        ###############################################
        
        availableratetobedistributed = maxrate
        
        if ((availableratetobedistributed != 0)
            and (1 - (self.queue.totals_kb[dir] / availableratetobedistributed) > 0.20)):
            #print "FREE WHEELING TORRENTS"
            # If there's still at least 20% of available bandwidth, let the torrents do want they want
            # Keep a reserved max rate updated not to have to reinitilize it when we'll switch later
            # from free wheeling to controlled status.
            # Give BitTornado the highest possible value for max rate to speed up the rate rising
            for torrent in workingset:
                newrate = torrent.connection.rate[dir] + self.meancalcupth
                maxlocalrate = float(torrent.connection.getLocalRate(dir))
                if maxlocalrate > 0:
                    rateToUse = maxlocalrate
                    if newrate > maxlocalrate:
                        newrate = maxlocalrate
                else:
                    rateToUse = self.MaxRate(dir)
                torrent.connection.maxrate[dir] = newrate
                # Send to BitTornado
                torrent.connection.setRate(rateToUse, dir)
            return

        ###########################################################################
        # First treat special torrents before going on sharing and distributing
        ###########################################################################

        # Treat in priority the torrents with rate below 3 kB/s and that want to get a higher rate
        grantedfortoberaisedinpriority = 0.0
        for torrent in toberaisedinpriority:
            newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
            if newreservedrate > self.rateminimum[dir]:
                grantedfortoberaisedinpriority += self.rateminimum[dir] - torrent.connection.maxrate[dir]
                torrent.connection.maxrate[dir] = self.rateminimum[dir]
            else:
                grantedfortoberaisedinpriority += newreservedrate - torrent.connection.maxrate[dir]
                torrent.connection.maxrate[dir] = newreservedrate

        # Treat in priority the torrents with a local rate setting if "prioritize local" is set
        # As with the free wheeling torrents, keep on tracking the real value of rate while giving BitTornado
        # the highest max rate to speed up the rate rising.
        grantedforlocaltoberaised = 0.0
        for torrent in localprioactive:
            newrate = torrent.connection.rate[dir] + self.meancalcupth
            maxlocalrate = float(torrent.connection.getLocalRate(dir))
            if newrate > maxlocalrate:
                newrate = maxlocalrate
            grantedforlocaltoberaised += newrate - torrent.connection.maxrate[dir]
            torrent.connection.maxrate[dir] = newrate
            # Send to BitTornado
            torrent.connection.setRate(maxlocalrate, dir)

        # Torrents that want to be lowered in rate (and give back some reserved bandwidth)
        givenbackbytobelowered = 0.0
        for torrent in tobelowered:
            newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
            givenbackbytobelowered += newreservedrate - torrent.connection.maxrate[dir]
            torrent.connection.maxrate[dir] = newreservedrate
        
        # Add to available rate to be distributed the rate given back by the torrents that have been lowered ;
        # Substract from available rate the rate used for each torrent that have been be raised in priority (torrents with rate
        # below 3 kB/s and that want to get higher).
        availableratetobedistributed += givenbackbytobelowered - grantedfortoberaisedinpriority - grantedforlocaltoberaised - self.queue.totals_kb[dir]
        #print "availableratetobedistributed is %.3f" % availableratetobedistributed

        # localprioactive torrents have already been updated if prioritizelocal is set
        toberegulated = [torrent for torrent in workingset if torrent not in localprioactive]

        # There's nothing to do if no torrent want to be raised
        if not toberaised:
            ################################################
            # Set new max rate to all active torrents
            ################################################
            for torrent in toberegulated:
                torrent.connection.setRate(torrent.connection.maxrate[dir], dir)
            return
               
        if availableratetobedistributed > 0:
            ###########################################################################
            #print "PHASE 1"
            ###########################################################################
            # Phase 1 : As long as there's available bandwidth below the total max to be distributed, I give some
            # to any torrents that asks for it.
            # There's a special case with torrents to be raised that have a local max rate : they must be topped to their max local
            # rate and the surplus part of the reserved bandwidth may be reused.
            # To sum up : In Phase 1, the measured rate is leading the reserved rate.

            # Check if all torrents that claim a higher reserved rate will be satisfied
            claimedrate = 0.0
            for torrent in toberaised:
                maxup = torrent.connection.maxrate[dir]
                newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
                toadd = newreservedrate

                maxlocalup = float(torrent.connection.getLocalRate(dir))
                if maxlocalup > 0 and newreservedrate > maxlocalup:
                    toadd = maxlocalup
                
                claimedrate += toadd - maxup

            #print "Claimed rate :", claimedrate
            #print "Available rate :", availableratetobedistributed

            if claimedrate <= availableratetobedistributed:
                realupfactor = 1
            else:
                realupfactor = availableratetobedistributed / claimedrate

            # If all claims can be fulfilled ; we distribute and go to end.
            # If there's not enough remaining rate to fulfill all claims, the remaining available rate will be
            # distributed proportionally between all torrents that want to raise.
            for torrent in toberaised:
                maxup = torrent.connection.maxrate[dir]
                newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
                newmaxup = maxup + (newreservedrate - maxup) * realupfactor

                maxlocalup = float(torrent.connection.getLocalRate(dir))
                if maxlocalup > 0 and newreservedrate > maxlocalup:
                    newmaxup = maxup + (maxlocalup - maxup) * realupfactor

                torrent.connection.maxrate[dir] = newmaxup
                #print "index :", torrent.listindex, "; rate raised from", maxup, "to", torrent.connection.maxrate[dir]
            
            ################################################
            # Set new max rate to all active torrents
            ################################################
            for torrent in toberegulated:
                torrent.connection.setRate(torrent.connection.maxrate[dir], dir)
            return

        ###########################################################################
        #print "PHASE 2"
        ###########################################################################
        # -a- Each torrent that wants its rate to be raised or not to be changed will have its reserved rate lowered
        #     to compensate the bandwidth given in priority to torrents with rate below 3 kB/s and torrents with local rate
        #     settings if "prioritize local" is set. This lowering must not bring the reserved rate of a torrent below 3 kB/s.
        #     Torrents will be sorted by their reserved rate and treated from the lower to the bigger. If a part of the lowering
        #     cannot be achieved with a torrent,it will be dispatched to the pool of the remaining torrents to be treated.
        #     After this, there may still be more total rate reserved than available rate because of the min 3 kB/s rule.
        ###########################################################################

        # -a-
        if availableratetobedistributed < 0:
            rate_id = []
            pooltobelowered = toberaised + nottobechanged
            
            rate_id = [torrent for torrent in pooltobelowered if torrent.connection.rate[dir] > self.rateminimum[dir]]

            sizerate_id = len(rate_id)
            # Sort by increasing reserved rate
            rate_id.sort(key = lambda x: x.connection.maxrate[dir])
            if rate_id:
                ratenotassignedforeach = availableratetobedistributed / sizerate_id
            # Compute new reserved rate
            i = 0
            for torrent in rate_id:
                # (availableratetobedistributed and ratenotassignedforeach are negative numbers)
                newmaxrate = torrent.connection.maxrate[dir] + ratenotassignedforeach
                i += 1
                if newmaxrate < self.rateminimum[dir]:
                    # if some rate lowering could not be dispatched, it will be distributed to the next torrents
                    # in the list (which are higher in max rate because the list is sorted this way)
                    if i != sizerate_id:
                        ratenotassignedforeach += (newmaxrate - self.rateminimum[dir]) / (sizerate_id - i)
                    newmaxrate = self.rateminimum[dir]
                torrent.connection.maxrate[dir] = newmaxrate
            #    print "%i lowered from %.3f to %.3f" % (t[1].listindex, t[0], newmaxrate)
            #print "availableratetobedistributed is now %.3f" % availableratetobedistributed

        ###########################################################################
        #print "PHASE 2 algo with mean rate"
        ###########################################################################
        # Phase 2 : There's no more available bandwidth to be distributed, I split the total max between active torrents.
        # -b- Compute the mean max rate for the pool of torrents that want their rate to be raised or not to be changed
        #     and list torrents below and above that mean value.
        # -c- The regulation for torrents that want to have their rate raised is computed this way :
        #     The idea is to target a mean rate for all torrents that want to raise their rate or don't want to have it
        #     changed, taking into account the max rates of local settings, and the fact that no torrent must be lowered down below
        #     3 kB/s.
        # To sum up : In Phase 2, the reserved rate is leading the real rate .

        # -b-
        # Mean reserved rate calculation
        # If prioritizelocal is set, all torrents with a local rate settting are completely excluded from
        # the bandwidth exchange phase between other torrents. This is because this phase
        # targets a mean rate between torrents that want to upload more, and when prioritizelocal
        # is set, torrents with a local rate settting can be very far from this mean rate and their
        # own purpose is not to integrate the pool of other torrents but to live their own life (!)

        if toberaised or nottobechanged:
            meanrate /= len(toberaised) + len(nottobechanged)
        #print "Mean rate over 3 kB/s : %.1f" % meanrate

        raisedbelowm = []         # ids for torrents to be raised and with reserved rate below mean max rate
        allabovem = []            # ids for torrents to be raised or not to be changed and with reserved rate above mean max rate
        
        for torrent in toberaised:
            if torrent.connection.maxrate[dir] > meanrate:
                allabovem.append(torrent)
            elif torrent.connection.maxrate[dir] < meanrate:
                raisedbelowm.append(torrent)
        for torrent in nottobechanged:
            if torrent.connection.maxrate[dir] > meanrate:
                allabovem.append(torrent)

        # -c-
        if raisedbelowm and allabovem:
            # Available bandwidth exchange :
            up = 0.0
            down = 0.0
            for torrent in raisedbelowm:
                toadd = meanrate - torrent.connection.maxrate[dir]

                maxlocalrate_float = float(torrent.connection.getLocalRate(dir))
                if maxlocalrate_float > 0 and maxlocalrate_float <= meanrate:
                    toadd = maxlocalrate_float - torrent.connection.maxrate[dir]
                up += toadd
            for torrent in allabovem:
                down += torrent.connection.maxrate[dir] - meanrate
            if up > down:
                limitup = down / up
            
            # Speed up slow torrents that want their rate to be raised :
            # Each one must have its reserved rate raised slowly enough to let it follow this raise if it really
            # wants to get higher. If we set the reserved to the max in one shot, these torrents will be then detected
            # in the next phase 1 as to be lowered, which is not what we want.
            realup = 0.0
            for torrent in raisedbelowm:
                maxup = torrent.connection.maxrate[dir]
                toadd = meanrate - maxup

                maxlocalrate_float = float(torrent.connection.getLocalRate(dir))
                if maxlocalrate_float > 0 and maxlocalrate_float <= meanrate:
                    toadd = maxlocalrate_float - maxup

                if up > down:
                    toadd *= limitup
                # step is computed such as if the torrent keeps on raising at the same rate as before, it will be
                # analysed as still wanting to raise by the next phase 1 check
                step = 2 * (torrent.connection.rate[dir] + self.calcupth2 - maxup)
                if toadd < step:
                    torrent.connection.maxrate[dir] = maxup + toadd
                    realup += toadd
                else:
                    torrent.connection.maxrate[dir] = maxup + step
                    realup += step
                #print "index :", torrent.listindex, "; rate raised from", maxup, "to", torrent.connection.maxrate[dir]          
            realup /= len(allabovem)
            # Slow down fast torrents :
            for torrent in allabovem:
                maxup = torrent.connection.maxrate[dir]
                torrent.connection.maxrate[dir] = maxup - realup
                #print "index :", torrent.listindex, "; rate lowered from", maxup, "to", torrent.listindex

        ################################################
        # Set new max rate to all active torrents
        ################################################
        for torrent in toberegulated:
            torrent.connection.setRate(torrent.connection.maxrate[dir], dir)
Example #3
0
    def CalculateBandwidth(self, dir="up"):
        if dir == "up":
            workingset = union(self.utility.torrents["downloading"],
                               self.utility.torrents["seeding"])
        else:
            workingset = self.utility.torrents["downloading"]

        # Limit working set to active torrents with connections:
        workingset = [
            torrent for torrent in workingset if torrent.status.isActive()
            and torrent.connection.engine.hasConnections
        ]

        # No active file, not need to calculate
        if not workingset:
            return

        maxrate = self.MaxRate(dir)
        # See if global rate settings are set to unlimited
        if maxrate == 0:
            # Unlimited rate
            for torrent in workingset:
                torrent.connection.maxrate[
                    dir] = torrent.connection.getLocalRate(dir)
                torrent.connection.setRate(torrent.connection.maxrate[dir],
                                           dir)
            return

        #print "====================== BEGINNING ALGO ======= th1=%.1f ; th2=%.1f =============================" % (self.calcupth1, self.calcupth2)

        #######################################################
        # - Find number of completed/incomplete torrent
        # - Number of torrent using local setting
        # - bandwidth already used by torrents
        # - Sorting of torrents in lists according to their will in matter of upload rate :
        #   (tobelowered, toberaisedinpriority, toberaised, nottobechanged)
        #######################################################

        # Option set in Preferences/Queue.
        # If not set, torrents with rate local settings are treated like other torrents, except they have their
        # own max rate they can't cross over. The consequence is a behaviour slightly different from the behavior of
        # ABC releases prior to 2.7.0.
        # If set, this gives the algorithm the behaviour of ABC releases prior to 2.7.0 : the torrents with an rate
        # local setting will be granted bandwidth in priority to fulfill their local setting, even is this one
        # is higher than the global max rate setting, and even if this bandwidth must be taken from other active
        # torrents wihout a local rate setting. These torrents will not take part in the rate exchange
        # between active torrents when all bandwidth has been distributed, since they will have been served in priority.
        prioritizelocal = self.utility.config.Read('prioritizelocal',
                                                   "boolean")

        # torrents with local rate settings when prioritizelocal is set (see prioritizelocal)
        localprioactive = []

        # torrents for which measured rate is lowering and so reserved rate can be lowered
        tobelowered = []

        # torrents for which measured rate is growing and so reserved rate can be raised,
        # (with reserved rate > 3 kB/s for uploading)
        toberaised = []

        # torrents for which reserved rate can be raised, with reserved rate < 3 kB/s
        # These will always be raised even there's no available up bandwith, to fulfill the min 3 kB/s rate rule
        toberaisedinpriority = []

        # torrents for which reserved rate is not to be changed and is > rateminimum; (for these, the
        # measured rate is between (max upload reserved - calcupth1) and (max upload reserved - calcupth2)
        nottobechanged = []

        meanrate = 0.0  # mean max rate for torrents to be raised or not to be changed ; it will be used to decide which torrents
        # must be raised amongst those that want to get higher and that must share the available up bandwidth. The torrents
        # that don't want to change their rate and that are below 3 kB/s are not taken into account on purpose, because
        # these ones will never be lowered to give more rate to a torrent that wants to raise its rate, or to
        # compensate for the rate given to torrents to be raised in priority.

        for torrent in workingset:
            # Active Torrent
            currentrate = torrent.connection.rate[dir]

            maxrate_float = torrent.connection.maxrate[dir]

            # Torrents dispatch
            if prioritizelocal and torrent.connection.getLocalRate(dir, True):
                localprioactive.append(torrent)
            elif currentrate < 0.05:
                # These are the torrents that don't want to have their rate changed and that have an allmost null rate
                # They will not go lower, we can reset their reserved rate until they want to get higher
                torrent.connection.maxrate[dir] = 0.0
            elif maxrate_float - currentrate > self.calcupth1:
                tobelowered.append(torrent)
            elif maxrate_float - currentrate <= self.calcupth2:
                if currentrate < self.rateminimum[dir]:
                    toberaisedinpriority.append(torrent)
                else:
                    toberaised.append(torrent)
                    meanrate += maxrate_float
            elif currentrate > self.rateminimum[dir]:
                nottobechanged.append(torrent)
                meanrate += maxrate_float

#        print "index: %i ; rate: %.1f ; reserved: %.1f ; maxlocal: %.1f" % (torrent.listindex, \
#              currentrate, maxrate_float, float(torrent.connection.maxlocalrate[dir]))

###############################################
# Calculate rate for each torrent
###############################################

        availableratetobedistributed = maxrate

        if ((availableratetobedistributed != 0) and
            (1 - (self.queue.totals_kb[dir] / availableratetobedistributed) >
             0.20)):
            #print "FREE WHEELING TORRENTS"
            # If there's still at least 20% of available bandwidth, let the torrents do want they want
            # Keep a reserved max rate updated not to have to reinitilize it when we'll switch later
            # from free wheeling to controlled status.
            # Give BitTornado the highest possible value for max rate to speed up the rate rising
            for torrent in workingset:
                newrate = torrent.connection.rate[dir] + self.meancalcupth
                maxlocalrate = float(torrent.connection.getLocalRate(dir))
                if maxlocalrate > 0:
                    rateToUse = maxlocalrate
                    if newrate > maxlocalrate:
                        newrate = maxlocalrate
                else:
                    rateToUse = self.MaxRate(dir)
                torrent.connection.maxrate[dir] = newrate
                # Send to BitTornado
                torrent.connection.setRate(rateToUse, dir)
            return

        ###########################################################################
        # First treat special torrents before going on sharing and distributing
        ###########################################################################

        # Treat in priority the torrents with rate below 3 kB/s and that want to get a higher rate
        grantedfortoberaisedinpriority = 0.0
        for torrent in toberaisedinpriority:
            newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
            if newreservedrate > self.rateminimum[dir]:
                grantedfortoberaisedinpriority += self.rateminimum[
                    dir] - torrent.connection.maxrate[dir]
                torrent.connection.maxrate[dir] = self.rateminimum[dir]
            else:
                grantedfortoberaisedinpriority += newreservedrate - torrent.connection.maxrate[
                    dir]
                torrent.connection.maxrate[dir] = newreservedrate

        # Treat in priority the torrents with a local rate setting if "prioritize local" is set
        # As with the free wheeling torrents, keep on tracking the real value of rate while giving BitTornado
        # the highest max rate to speed up the rate rising.
        grantedforlocaltoberaised = 0.0
        for torrent in localprioactive:
            newrate = torrent.connection.rate[dir] + self.meancalcupth
            maxlocalrate = float(torrent.connection.getLocalRate(dir))
            if newrate > maxlocalrate:
                newrate = maxlocalrate
            grantedforlocaltoberaised += newrate - torrent.connection.maxrate[
                dir]
            torrent.connection.maxrate[dir] = newrate
            # Send to BitTornado
            torrent.connection.setRate(maxlocalrate, dir)

        # Torrents that want to be lowered in rate (and give back some reserved bandwidth)
        givenbackbytobelowered = 0.0
        for torrent in tobelowered:
            newreservedrate = torrent.connection.rate[dir] + self.meancalcupth
            givenbackbytobelowered += newreservedrate - torrent.connection.maxrate[
                dir]
            torrent.connection.maxrate[dir] = newreservedrate

        # Add to available rate to be distributed the rate given back by the torrents that have been lowered ;
        # Substract from available rate the rate used for each torrent that have been be raised in priority (torrents with rate
        # below 3 kB/s and that want to get higher).
        availableratetobedistributed += givenbackbytobelowered - grantedfortoberaisedinpriority - grantedforlocaltoberaised - self.queue.totals_kb[
            dir]
        #print "availableratetobedistributed is %.3f" % availableratetobedistributed

        # localprioactive torrents have already been updated if prioritizelocal is set
        toberegulated = [
            torrent for torrent in workingset if torrent not in localprioactive
        ]

        # There's nothing to do if no torrent want to be raised
        if not toberaised:
            ################################################
            # Set new max rate to all active torrents
            ################################################
            for torrent in toberegulated:
                torrent.connection.setRate(torrent.connection.maxrate[dir],
                                           dir)
            return

        if availableratetobedistributed > 0:
            ###########################################################################
            #print "PHASE 1"
            ###########################################################################
            # Phase 1 : As long as there's available bandwidth below the total max to be distributed, I give some
            # to any torrents that asks for it.
            # There's a special case with torrents to be raised that have a local max rate : they must be topped to their max local
            # rate and the surplus part of the reserved bandwidth may be reused.
            # To sum up : In Phase 1, the measured rate is leading the reserved rate.

            # Check if all torrents that claim a higher reserved rate will be satisfied
            claimedrate = 0.0
            for torrent in toberaised:
                maxup = torrent.connection.maxrate[dir]
                newreservedrate = torrent.connection.rate[
                    dir] + self.meancalcupth
                toadd = newreservedrate

                maxlocalup = float(torrent.connection.getLocalRate(dir))
                if maxlocalup > 0 and newreservedrate > maxlocalup:
                    toadd = maxlocalup

                claimedrate += toadd - maxup

            #print "Claimed rate :", claimedrate
            #print "Available rate :", availableratetobedistributed

            if claimedrate <= availableratetobedistributed:
                realupfactor = 1
            else:
                realupfactor = availableratetobedistributed / claimedrate

            # If all claims can be fulfilled ; we distribute and go to end.
            # If there's not enough remaining rate to fulfill all claims, the remaining available rate will be
            # distributed proportionally between all torrents that want to raise.
            for torrent in toberaised:
                maxup = torrent.connection.maxrate[dir]
                newreservedrate = torrent.connection.rate[
                    dir] + self.meancalcupth
                newmaxup = maxup + (newreservedrate - maxup) * realupfactor

                maxlocalup = float(torrent.connection.getLocalRate(dir))
                if maxlocalup > 0 and newreservedrate > maxlocalup:
                    newmaxup = maxup + (maxlocalup - maxup) * realupfactor

                torrent.connection.maxrate[dir] = newmaxup
                #print "index :", torrent.listindex, "; rate raised from", maxup, "to", torrent.connection.maxrate[dir]

            ################################################
            # Set new max rate to all active torrents
            ################################################
            for torrent in toberegulated:
                torrent.connection.setRate(torrent.connection.maxrate[dir],
                                           dir)
            return

        ###########################################################################
        #print "PHASE 2"
        ###########################################################################
        # -a- Each torrent that wants its rate to be raised or not to be changed will have its reserved rate lowered
        #     to compensate the bandwidth given in priority to torrents with rate below 3 kB/s and torrents with local rate
        #     settings if "prioritize local" is set. This lowering must not bring the reserved rate of a torrent below 3 kB/s.
        #     Torrents will be sorted by their reserved rate and treated from the lower to the bigger. If a part of the lowering
        #     cannot be achieved with a torrent,it will be dispatched to the pool of the remaining torrents to be treated.
        #     After this, there may still be more total rate reserved than available rate because of the min 3 kB/s rule.
        ###########################################################################

        # -a-
        if availableratetobedistributed < 0:
            rate_id = []
            pooltobelowered = toberaised + nottobechanged

            rate_id = [
                torrent for torrent in pooltobelowered
                if torrent.connection.rate[dir] > self.rateminimum[dir]
            ]

            sizerate_id = len(rate_id)
            # Sort by increasing reserved rate
            rate_id.sort(key=lambda x: x.connection.maxrate[dir])
            if rate_id:
                ratenotassignedforeach = availableratetobedistributed / sizerate_id
            # Compute new reserved rate
            i = 0
            for torrent in rate_id:
                # (availableratetobedistributed and ratenotassignedforeach are negative numbers)
                newmaxrate = torrent.connection.maxrate[
                    dir] + ratenotassignedforeach
                i += 1
                if newmaxrate < self.rateminimum[dir]:
                    # if some rate lowering could not be dispatched, it will be distributed to the next torrents
                    # in the list (which are higher in max rate because the list is sorted this way)
                    if i != sizerate_id:
                        ratenotassignedforeach += (newmaxrate -
                                                   self.rateminimum[dir]) / (
                                                       sizerate_id - i)
                    newmaxrate = self.rateminimum[dir]
                torrent.connection.maxrate[dir] = newmaxrate
            #    print "%i lowered from %.3f to %.3f" % (t[1].listindex, t[0], newmaxrate)
            #print "availableratetobedistributed is now %.3f" % availableratetobedistributed

        ###########################################################################
        #print "PHASE 2 algo with mean rate"
        ###########################################################################
        # Phase 2 : There's no more available bandwidth to be distributed, I split the total max between active torrents.
        # -b- Compute the mean max rate for the pool of torrents that want their rate to be raised or not to be changed
        #     and list torrents below and above that mean value.
        # -c- The regulation for torrents that want to have their rate raised is computed this way :
        #     The idea is to target a mean rate for all torrents that want to raise their rate or don't want to have it
        #     changed, taking into account the max rates of local settings, and the fact that no torrent must be lowered down below
        #     3 kB/s.
        # To sum up : In Phase 2, the reserved rate is leading the real rate .

        # -b-
        # Mean reserved rate calculation
        # If prioritizelocal is set, all torrents with a local rate settting are completely excluded from
        # the bandwidth exchange phase between other torrents. This is because this phase
        # targets a mean rate between torrents that want to upload more, and when prioritizelocal
        # is set, torrents with a local rate settting can be very far from this mean rate and their
        # own purpose is not to integrate the pool of other torrents but to live their own life (!)

        if toberaised or nottobechanged:
            meanrate /= len(toberaised) + len(nottobechanged)
        #print "Mean rate over 3 kB/s : %.1f" % meanrate

        raisedbelowm = [
        ]  # ids for torrents to be raised and with reserved rate below mean max rate
        allabovem = [
        ]  # ids for torrents to be raised or not to be changed and with reserved rate above mean max rate

        for torrent in toberaised:
            if torrent.connection.maxrate[dir] > meanrate:
                allabovem.append(torrent)
            elif torrent.connection.maxrate[dir] < meanrate:
                raisedbelowm.append(torrent)
        for torrent in nottobechanged:
            if torrent.connection.maxrate[dir] > meanrate:
                allabovem.append(torrent)

        # -c-
        if raisedbelowm and allabovem:
            # Available bandwidth exchange :
            up = 0.0
            down = 0.0
            for torrent in raisedbelowm:
                toadd = meanrate - torrent.connection.maxrate[dir]

                maxlocalrate_float = float(
                    torrent.connection.getLocalRate(dir))
                if maxlocalrate_float > 0 and maxlocalrate_float <= meanrate:
                    toadd = maxlocalrate_float - torrent.connection.maxrate[dir]
                up += toadd
            for torrent in allabovem:
                down += torrent.connection.maxrate[dir] - meanrate
            if up > down:
                limitup = down / up

            # Speed up slow torrents that want their rate to be raised :
            # Each one must have its reserved rate raised slowly enough to let it follow this raise if it really
            # wants to get higher. If we set the reserved to the max in one shot, these torrents will be then detected
            # in the next phase 1 as to be lowered, which is not what we want.
            realup = 0.0
            for torrent in raisedbelowm:
                maxup = torrent.connection.maxrate[dir]
                toadd = meanrate - maxup

                maxlocalrate_float = float(
                    torrent.connection.getLocalRate(dir))
                if maxlocalrate_float > 0 and maxlocalrate_float <= meanrate:
                    toadd = maxlocalrate_float - maxup

                if up > down:
                    toadd *= limitup
                # step is computed such as if the torrent keeps on raising at the same rate as before, it will be
                # analysed as still wanting to raise by the next phase 1 check
                step = 2 * (torrent.connection.rate[dir] + self.calcupth2 -
                            maxup)
                if toadd < step:
                    torrent.connection.maxrate[dir] = maxup + toadd
                    realup += toadd
                else:
                    torrent.connection.maxrate[dir] = maxup + step
                    realup += step
                #print "index :", torrent.listindex, "; rate raised from", maxup, "to", torrent.connection.maxrate[dir]
            realup /= len(allabovem)
            # Slow down fast torrents :
            for torrent in allabovem:
                maxup = torrent.connection.maxrate[dir]
                torrent.connection.maxrate[dir] = maxup - realup
                #print "index :", torrent.listindex, "; rate lowered from", maxup, "to", torrent.listindex

        ################################################
        # Set new max rate to all active torrents
        ################################################
        for torrent in toberegulated:
            torrent.connection.setRate(torrent.connection.maxrate[dir], dir)