abcengine.py :  » Network » Torrent-Swapper » swapper » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Torrent Swapper 
Torrent Swapper » swapper » abcengine.py
import wx
import sys
from socket import inet_aton

#from operator import itemgetter
from threading import Event,Timer,currentThread
from time import time,sleep
#from cStringIO import StringIO
from traceback import print_stack,print_exc
from binascii import unhexlify

from BitTornado.download_bt1 import BT1Download
from BitTornado.clock import clock

from Utility.constants import *#IGNORE:W0611
fromUtility.helpersgetfreespace

from Swapper.Worldmap.peer import BTPeer
from Swapper.CacheDB.CacheDBHandler import FriendDBHandler

from safeguiupdate import DelayedEventHandler

from Swapper.Overlay.permid import show_permid

DEBUG = False


################################################################
#
# Class: ABCEngine
#
# This is the part of a torrent object created while it is
# active.  It handles processing of statistics and information
# from the BitTornado core.
#
################################################################
class ABCEngine(DelayedEventHandler):
    def __init__(self, torrent, myid):
        DelayedEventHandler.__init__(self)
        self.doneflag = Event()

        self.torrent = torrent
        self.queue = torrent.queue
        self.utility = torrent.utility

        self.downsize = { 'old' : torrent.files.downsize, 
                          'new' : 0.0 }
        self.upsize = { 'old' : torrent.files.upsize, 
                        'new' : 0.0 }
        
        self.spewwait = time()

        self.reannouncelast = 0
        self.lastexternalannounce = ''

        self.timers = { 'lastupload': time(), 
                        'lastdownload': time(),
                        'infrequent': None }

        self.btstatus = self.utility.lang.get('waiting')
        self.progress = torrent.files.progress
        
        self.eta = None
        self.rate = { "down" : 0.0, 
                      "up" : 0.0 }

        self.numpeers = 0
        self.numseeds = 0

        self.numconnections = 0
        self.numcopies = None
        self.peeravg = None
        self.totalspeed = 0.0
        self.numerrortracker=0
        self.lasterrortracker=0
        
        self.current_ratesetting = None
        
        self.seedingtimelastcheck = None

        # To compute mean over several last values of uprate/downrate        
        self.pastrate = { "down" : [0.0] * 20, 
                          "up" : [0.0] * 20 }
        self.meanrate = { "down" : 0.0, 
                          "up" : 0.0 }
                     
        # Keep track of if we have any connections
        self.hasConnections = False
        
        # New stuff....

        self.controller = self.utility.controller
        
        self.waiting = True
        self.checking = False
        self.working = False
        self.seed = False
        self.closed = False

        self.status_err = ['']
        self.status_errtime = 0
        self.status_done = 0.0
        
        self.response = self.torrent.metainfo
        hash = unhexlify(self.torrent.infohash)

        self.rawserver = self.controller.handler.newRawServer(hash, self.doneflag)

        # TODO: Workaround for multiport not reporting
        #       external_connection_made properly
        self.workarounds = { 'hasexternal': False }
        
        self.color = 'color_startup'
        self.downloadHelpers = []
        self.fileProgressPostponeCounter = 0
        
        btconfig = self.utility.getBTParams()
        # 2fastbt_
        if self.torrent.caller == "helper":
            btconfig['role'] = 'helper'
            btconfig['coordinator_permid'] = self.torrent.caller_data['coordinator_permid']
            msg = self.utility.lang.get('helping_friend') + self.torrent.caller_data['friendname']
            self.errormsgCallback( msg, "status")
        else:
            btconfig['role'] = 'coordinator'
            btconfig['helpers_file'] = ''
         # _2fastbt

#        # TODO: setting check_hashes doesn't seem to work quite right
#        #
#        # Only do reseed resume if the size of the files matches
#        # the size that they are supposed to be
#        # (Should prevent errors in at least some cases)
#        if self.torrent.files.getSpaceNeeded(realsize = False) == 0:
#            if self.torrent.files.skipcheck or \
#               (self.torrent.status.completed and self.utility.config.Read('skipcheck', "boolean")):
#                btconfig['check_hashes'] = 0
#        self.torrent.files.skipcheck = False

        self.dow = BT1Download(self.display, 
                               self.finished, 
                               self.error, 
                               self.controller.exchandler, 
                               self.doneflag, 
                               btconfig,
                               self.response, 
                               hash, 
                               myid, 
                               self.rawserver, 
                               self.controller.listen_port)


    ####################################
    # BEGIN NEW STUFF (FOR SINGLE PORT)
    ####################################

    def start(self):
        # Delete the cache information if doing a hashcheck
        # (only necessary to delete the cache if fastresume is enabled)
        if ((self.torrent.status.value == STATUS_HASHCHECK) and
            self.utility.config.Read('fastresume', "boolean")):
            self.dow.appdataobj.deleteTorrentData(self.dow.infohash)
               
        if not self.dow.saveAs(self.saveAs):
            self.shutdown()
            return
        self._hashcheckfunc = self.dow.initFiles()

        if not self._hashcheckfunc:
            self.shutdown()
            return

        self.controller.hashchecksched(self.torrent)

    def hashcheck_start(self, donefunc):
        if self.is_dead():
            self.shutdown()
            return
        self.waiting = False
        self.checking = True
        
        # Start infrequent tasks
        self.InfrequentTasks()
        
        self._hashcheckfunc(donefunc)

    def hashcheck_callback(self):
        self.checking = False
               
        if self.is_dead():
            self.shutdown()
            return
        
        if not self.dow.startEngine(ratelimiter = None):
            self.shutdown()
            return

        self.dow.startRerequester()

        self.statsfunc = self.dow.startStats()

        if self.torrent.status.value != STATUS_HASHCHECK:
            self.torrent.status.updateStatus(STATUS_ACTIVE)

        self.torrent.files.setFilePriorities()
        self.torrent.connection.setMaxInitiate()
        
        # Set the spew flag if the detail window is shown
        if self.torrent.dialogs.details is not None:
            self.dow.spewflag.set()

        # TODO: Workaround for multiport not reporting
        #       external_connection_made properly
        self.dow.spewflag.set()
               
        self.rawserver.start_listening(self.dow.getPortHandler())
        self.working = True

    def shutdown(self):
        if DEBUG:
            print "engine: Starting shutdown"
        # Remove from the active torrents list
        try:
            del self.utility.torrents["active"][self.torrent]
        except:
            pass

        self.stop_download_help()
            
        # Cancel timer
        try:
            if self.timers['infrequent'] is not None:
                self.timers['infrequent'].cancel()
        except:
            pass

        if self.closed:
            return
        self.doneflag.set()
        try:
            if DEBUG:
                print "engine: Shutting down SingleRawServer"
            self.rawserver.shutdown()
        except:
            print_exc()
            pass

        try:
            self.dow.shutdown()
        except:
            pass
        self.waiting = False
        self.checking = False
        self.working = False
        self.closed = True

        self.controller.was_stopped(self.torrent)

    def display(self, activity = None, fractionDone = None):
        # really only used by StorageWrapper now
        self.setActivity(activity)
        if fractionDone is not None:
            self.status_done = float(fractionDone)

    def error(self, msg):
        if DEBUG:
            print "engine: Error",msg
        if self.doneflag.isSet():
            # delegate updating GUI error message to launchmany core, as
            # we're dying.
            self.controller.dying_engines_errormsg(self.torrent,msg,"error")
            self.shutdown()
        else:
            self.errormsg(msg)
        self.status_err.append(msg)
        self.status_errtime = clock()


    def saveAs(self, name, length, saveas, isdir):
        return self.torrent.files.dest
        
    def done(self, event = None):
        self.torrent.set()
        
    def is_dead(self):
        return self.doneflag.isSet()
        
    ####################################
    # END NEW STUFF (FOR SINGLE PORT)
    ####################################
        
    def setActivity(self, activity):
        if activity is not None:
            activities = { "checking existing data": self.utility.lang.get('checkingdata'), 
                           "allocating disk space": self.utility.lang.get('allocatingspace'), 
                           "moving data": self.utility.lang.get('movingdata') }
            self.btstatus = activities.get(activity, activity)

    def onUpdateStatus(self, fractionDone = None, 
            timeEst = None, downRate = None, upRate = None, 
            activity = None, statistics = None, spew = None, 
            **kws):

        self.invokeLater(self.updateStatus, [fractionDone, timeEst, downRate, upRate, activity, statistics, spew])

        
    def updateStatus(self, fractionDone = None, timeEst = None, downRate = None, upRate = None, activity = None, statistics = None, spew = None):
        # Just in case a torrent was finished
        # but now isn't
        self.torrent.status.completed = self.seed
            
        # Get scrape data every 20 minutes
        #############################################
        if self.utility.config.Read('scrape', "boolean"):
            self.torrent.actions.scrape()
       
        # Get Display Data
        #############################################
        if fractionDone is not None and not self.seed:
            self.progress = (float(fractionDone) * 100)

        self.setActivity(activity)

        if timeEst is not None:
            self.eta = timeEst
        else:
            self.eta = None
        
        if self.torrent.status.value != STATUS_PAUSE:
            if not self.seed and downRate is not None:
                self.rate['down'] = float(downRate)
                if self.rate['down'] != 0.0:
                    self.timers['lastdownload'] = time()
            else:
                self.rate['down'] = 0.0
                       
            if upRate is not None:
                self.rate['up'] = float(upRate)

                self.pastrate['up'].append(self.rate['up'])
                self.pastrate['up'].pop(0)

                if self.rate['up'] != 0.0:
                    self.timers['lastupload'] = time()

                # Compute mean uprate

                total = sum(self.pastrate['up'])
                self.meanrate['up'] = total / 20
            else:
                self.rate['up'] = 0.0

        if statistics is not None:
            self.numpeers   = statistics.numPeers
            self.numcopies  = statistics.numCopies
            self.peeravg    = statistics.percentDone

            # Update download, upload, and progress
            self.downsize['new'] = float(statistics.downTotal)
            self.upsize['new'] = float(statistics.upTotal)
            self.torrent.files.updateProgress()
            self.totalspeed = float(statistics.torrentRate)
            self.numconnections = statistics.numPeers

            if not self.seed:
                self.numseeds = statistics.numSeeds
                self.numconnections += statistics.numSeeds
            else:
                self.numseeds = statistics.numOldSeeds
        else:
            self.peeravg = None
            self.numcopies = None
        
        if self.seed:
            self.countSeedingTime()
            if self.torrent.status.isDoneUploading():
                self.TerminateUpload()

        # Update color
        self.updateColor(statistics, spew)

        # Update text strings
        self.torrent.updateColumns([COL_PROGRESS, 
                                    COL_BTSTATUS, 
                                    COL_ETA, 
                                    COL_DLSPEED, 
                                    COL_ULSPEED, 
                                    COL_MESSAGE])
        
        if statistics is not None:
            # Share Ratio, #Seed, #Peer, #Copies, #Peer Avg Progress,
            # Download Size, Upload Size, Total Speed
            self.torrent.updateColumns([COL_RATIO, 
                                        COL_SEEDS, 
                                        COL_PEERS, 
                                        COL_COPIES, 
                                        COL_PEERPROGRESS, 
                                        COL_DLSIZE, 
                                        COL_ULSIZE, 
                                        COL_TOTALSPEED, 
                                        COL_SEEDTIME, 
                                        COL_CONNECTIONS])

        # Update progress in details window
        if statistics is not None:
            # Arno: slow down file progress update by a factor for multi-file
            # torrents. Otherwise if the torrent has many files, the client will 
            # come to a halt.
            #print "engine: #files in stats",len(statistics.filecomplete)
            if self.fileProgressPostponeCounter == 0:
                self.torrent.files.updateFileProgress(statistics)
                if getattr(statistics,"filecomplete",None) is not None:
                    self.fileProgressPostponeCounter = int(len(statistics.filecomplete)/1000)
                else:
                    self.fileProgressPostponeCounter = 0
            else:
                self.fileProgressPostponeCounter -= 1

        if spew and len(spew) > 0:
            self.updateCaches(spew)

#        try:
            self.updateDetailWindow(statistics, spew)
#        except Exception, msg:
#            # Just in case the window gets set to "None"
#            # or is destroyed first
#            print Exception, msg
#        
        if self.torrent.status.value == STATUS_HASHCHECK and self.working:
            # Skip on ahead to the normal procedure if the torrent was active
            # before doing the hashcheck
            activevalues = [ STATUS_ACTIVE, STATUS_PAUSE, STATUS_SUPERSEED ]
            oldstatus = self.torrent.actions.oldstatus
            if not oldstatus in activevalues:
                self.shutdown()
                return
            else:
                self.torrent.status.updateStatus(STATUS_ACTIVE)
        
    # TODO: Workaround for multiport not reporting
    #       external_connection_made properly
    def getExternalConnectionsMade(self, spew):
        if self.workarounds['hasexternal']:
            return True
            
        # Consider at least one remote connection evidence of
        # an external connection being made
        for x in range(len(spew)):
            if spew[x]['direction'] == 'R':
                self.workarounds['hasexternal'] = True
            
                # We can clear the spewflag now...
                if self.torrent.dialogs.details is None:
                    self.dow.spewflag.clear()
                return True
            
        return False
        
    def updateColor(self, statistics = None, spew = None):
        ##################################################
        # Set colour :
        ##################################################
        color = None
        
        if currentThread().getName() != "MainThread":
            print "engine: updateColor thread",currentThread()
            print "engine: NOT MAIN THREAD"
            print_stack()

        if statistics is not None:
            externalConnectionMade = statistics.external_connection_made
        
            # TODO: Workaround for multiport not reporting
            #       external_connection_made properly
            if externalConnectionMade:
                self.workarounds['hasexternal'] = True
            else:
                externalConnectionMade = self.workarounds['hasexternal']
                if not externalConnectionMade and spew is not None:
                    externalConnectionMade = self.getExternalConnectionsMade(spew)
        
        if statistics is None: 
            color = 'color_startup' #Start up
            self.hasConnections = False
        elif statistics.numPeers + statistics.numSeeds + statistics.numOldSeeds == 0:
            if statistics.last_failed:
                #Disconnected
                color = 'color_disconnected'
            else:
                #No connections
                color = 'color_noconnections'
            self.hasConnections = False
        elif (not externalConnectionMade):
            #No incoming
            color = 'color_noincoming'
            self.hasConnections = True
        elif ((statistics.numSeeds + statistics.numOldSeeds == 0)
               and ((self.seed and statistics.numCopies < 1)
                or (not self.seed and statistics.numCopies2 < 1))):
            #No completes
            color = 'color_nocomplete'
            self.hasConnections = True
        else:
            #All Good
            color = 'color_good'
            self.hasConnections = True

        self.color = color
        self.torrent.updateColor()
    
    #
    # Things that don't need to be done on every pass through updateStatus
    #
    def InfrequentTasks(self):
        try:
            if self.timers['infrequent'] is not None:
                self.timers['infrequent'].cancel()
        except:
            pass
        
        self.CheckTimeouts()
        self.CheckDiskSpace()
        
        # Should check diskspace more frequently
        # while in the "allocating" stage
        if self.waiting or self.checking:
            nextcheck = 2
        else:
            nextcheck = 30
        
        self.timers['infrequent'] = Timer(nextcheck, self.InfrequentTasks)
        self.timers['infrequent'].start()
    
    #
    # Check to make sure that there's free diskspace
    #
    def CheckDiskSpace(self):
        threshold = self.utility.config.Read('diskfullthreshold', "int")
        
        # Disk checking is disabled
        if threshold == 0:
            return
        
        # See how much more space the torrent needs
        spaceneeded = self.torrent.files.getSpaceNeeded()
        
        # Don't need to worry if the torrent already has
        # as much space as it needs
        if spaceneeded == 0L:
            return
            
        dest = self.torrent.files.getProcDest(pathonly = True)
        if dest is None:
            # Don't bother checking for space until the
            # destination path exists
            return
            
        spaceleft = getfreespace(dest)
        if spaceleft < long((2**20) * threshold):
            message = self.utility.lang.get('diskfull') + \
                      " (" + self.utility.size_format(spaceleft) + ")"
            self.errormsg(message)
            self.actionhandlerCallback( STATUS_STOP, self.torrent )
    
    #
    # See if there's been a timeout
    #
    def CheckTimeouts(self):
        # Check to see if we need to check for timeouts
        if not self.torrent.connection.timeout or self.torrent.status.value == STATUS_PAUSE:
            return
        
        # Check no download transfer in 30 mins
        # (when this torrent is leeching torrent)
        ##########################################
        if not self.seed:
            timeoutdownload = self.utility.config.Read('timeoutdownload')
            if (timeoutdownload != 'oo'
                and (time() - self.timers['lastdownload']) > (float(timeoutdownload)*60)):
                self.ReducePrioandForceQueue()
                return

        # Check no upload transfer in 1 hour
        # (when this torrent is seeding torrent)
        ##########################################
        else:
            timeoutupload = self.utility.config.Read('timeoutupload')
            if ((timeoutupload != 'oo')
                and (time() - self.timers['lastupload']) > (float(timeoutupload)*3600)):
                self.ReducePrioandForceQueue()
                return

    def updateDetailWindow(self, statistics = None, spew = None):
        #####################################################
        # Detail Window display part
        #####################################################
        detailwin = self.torrent.dialogs.details
        if detailwin is None or not detailwin.update:
            return
        detailpanel = detailwin.detailPanel
        
        if statistics is not None:
            detailpanel.updateFromABCTorrent()
                      
        if spew is not None and (time() - self.spewwait > 1):
            self.updateSpewList(statistics, spew)

        if statistics is not None:
            detailpanel.storagestats1.SetLabel("          " + self.utility.lang.get('detailline1')
                             % (statistics.storage_active, 
                                 statistics.storage_new, 
                                 statistics.storage_dirty))
            detailpanel.storagestats2.SetLabel("          "+ self.utility.lang.get('detailline2')
                             % (statistics.storage_numcomplete, 
                                 statistics.storage_totalpieces, 
                                 statistics.storage_justdownloaded, 
                                 statistics.storage_numflunked))

    def updatePeersOnEarth(self, spew):
        """ update peer_swarm, delete non-actived peers, insert newcoming peers
        and update the position of peers in the earth panel
        note: each torrent has an abcengine
        """
        
        # set all peers as not alive and then only active all peers in spew
        for ip in self.torrent.peer_swarm.keys():
            self.torrent.peer_swarm[ip].active = False
            
        for peer_info in spew:
            ip = peer_info['ip']
            if self.torrent.peer_swarm.has_key(ip):  # if the peer exists, active it
                self.torrent.peer_swarm[ip].updateBTInfo(peer_info)
                self.torrent.peer_swarm[ip].active = True
            else:   # otherwise create a new peer, add it into peer_swarm and display it
                new_peer = BTPeer(peer_info, self.torrent, self.rawserver)
                new_peer.updateBTInfo(peer_info)
                self.torrent.peer_swarm[ip] = new_peer

    def updatePeerCache(self, spew):
        pass
        
    def updateFileCache(self, spew):
        pass

    def updateCaches(self, spew):
        """ update peers on earth map, peer cache and file cache """
        
        #print "update caches", len(spew), self
        self.updatePeersOnEarth(spew)    
        self.updatePeerCache(spew)    # the real update is in DownloaderFeedback.update*()
        self.updateFileCache(spew)
        
    def sortSpew(self, spew, sortcol, reversed):
        tmplist = [(self.getSpewColumnValue(sortcol, line, spew), spew[line]) for \
                    line in range(len(spew))]
        tmplist.sort()
        if reversed:
            tmplist.reverse()
        return [x for (_, x) in tmplist]
        
    def updateSpewList(self, statistics = None, spew = None):
        detailwin = self.torrent.dialogs.details
        if spew is None or detailwin is None or not detailwin.update:
            return
        
        self.spewwait = time()
        spewList = detailwin.detailPanel.spewList
        columns = spewList.columns

        numcols = len(columns.active)
        # (no point in doing anything if there aren't any columns to update)
        if numcols == 0:
            return

        spewlen = len(spew) + 3

        if statistics is not None:
            kickbanlen = len(statistics.peers_kicked)+len(statistics.peers_banned)
            if kickbanlen:
                spewlen += kickbanlen + 1
            if statistics.peers_kicked:
                spewlen += 1
            if statistics.peers_banned:
                spewlen += 1
        else:
            kickbanlen = 0
        
        try:
            for x in range(spewlen-spewList.GetItemCount()):
                i = wx.ListItem()
                spewList.InsertItem(i)
            for x in range(spewlen, spewList.GetItemCount()):
                spewList.DeleteItem(len(spew) + 1)
        except wx.PyDeadObjectError:
            pass
    
        tot_uprate = 0.0
        tot_downrate = 0.0
        
        sortcol, reversed = spewList.getSortInfo()
        if sortcol >= 0:
            spew = self.sortSpew(spew, sortcol, reversed)
        
        # Disabling itemgetter sorts to remain 2.3 compatible
        # Sort by uprate first
        #spew.sort(None, key=itemgetter('uprate'))
        #spew.reverse()
        #if not self.torrent.status.completed:
            # Then sort by downrate if not complete
            #spew.sort(None, key=itemgetter('downrate'))
            #spew.reverse()

        for x in range(len(spew)):                
            for colid, rank in columns.active:
                self.updateSpewColumnText(x, rank, self.getSpewColumnText(colid, x, spew))
            
            tot_uprate += spew[x]['uprate']
            tot_downrate += spew[x]['downrate']

        x = len(spew)
        for i in range(numcols):
            self.updateSpewColumnText(x, i, '')
 
        x += 1
        for colid, rank in columns.active:
            if colid == SPEW_IP:
                text = self.utility.lang.get('TOTALS')
            else:
                text = ''                    
            self.updateSpewColumnText(x, rank, text)

        x += 1
        for colid, rank in columns.active:
            if colid == SPEW_UP:
                text = self.utility.speed_format(tot_uprate, truncate = 0)
            elif colid == SPEW_DOWN:
                text = self.utility.speed_format(tot_downrate, truncate = 0)
            elif colid == SPEW_DLSIZE and statistics is not None:
                text = self.utility.size_format(float(statistics.downTotal))
            elif colid == SPEW_ULSIZE and statistics is not None:
                text = self.utility.size_format(float(statistics.upTotal))
            else:
                text = ''                    
            self.updateSpewColumnText(x, rank, text)
 
        if kickbanlen:
            x += 1
            for i in range(numcols):
                self.updateSpewColumnText(x, i, '')

            if statistics.peers_kicked:
                x += 1
                for colid, rank in columns.active:
                    if colid == SPEW_IP:
                        text = self.utility.lang.get('KICKED')
                    else:
                        text = ''                    
                    self.updateSpewColumnText(x, rank, text)

                for ip in statistics.peers_kicked:
                    x += 1
                    for colid, rank in columns.active:
                        if colid == SPEW_IP:
                            text = ip[1]
                        else:
                            text = ''                    
                        self.updateSpewColumnText(x, rank, text)

            if statistics.peers_banned:
                x += 1
                for colid, rank in columns.active:
                    if colid == SPEW_IP:
                        text = self.utility.lang.get('BANNED')
                    else:
                        text = ''                    
                    self.updateSpewColumnText(x, rank, text)

                for ip in statistics.peers_banned:
                    x += 1
                    for colid, rank in columns.active:
                        if colid == SPEW_IP:
                            text = ip[1]
                        else:
                            text = ''                    
                        self.updateSpewColumnText(x, rank, text)
        
    def updateSpewColumnText(self, line, colid, text):
        detailwin = self.torrent.dialogs.details
        if detailwin is None or not detailwin.update:
            return

        try:
            detailwin.detailPanel.spewList.SetStringItem(line, colid, text)
        except wx.PyDeadObjectError:
            pass
                
                
    def getSpewColumnValue(self, colid, line, spew):

        if colid == SPEW_UNCHOKE:
            return spew[line]
            
        elif colid == SPEW_IP:
            try:
                ip = spew[line]['ip']
                return inet_aton(ip)
            except:
                return ''
                
            x = s.find('.')
            if x == -1:
                return 0
            iptext = s[:x] + '.' + ''.join(s[x:].split('.'))
            return eval(iptext)
            
        elif colid == SPEW_LR:
            return spew[line]['direction']
            
        elif colid == SPEW_UP:
            return spew[line]['uprate']
            
        elif colid == SPEW_INTERESTED:
            return spew[line]['uinterested']
            
        elif colid == SPEW_CHOKING:
            return spew[line]['uchoked']
            
        elif colid == SPEW_DOWN:
            return spew[line]['downrate']
            
        elif colid == SPEW_INTERESTING:
            return spew[line]['dinterested']
            
        elif colid == SPEW_CHOKED:
            return spew[line]['dchoked']
            
        elif colid == SPEW_SNUBBED:
            return spew[line]['snubbed']
            
        elif colid == SPEW_DLSIZE:
            return spew[line]['dtotal']
            
        elif colid == SPEW_ULSIZE:
            if spew[line]['utotal'] is not None:
                return spew[line]['utotal']
            else:
                return 0
                
        elif colid == SPEW_PEERPROGRESS:
            return spew[line]['completed']
            
        elif colid == SPEW_PEERSPEED:
            if spew[line]['speed'] is not None:
                return spew[line]['speed']
            else:
                return 0

        elif colid == SPEW_PERMID:
            if spew[line]['unauth_permid'] is not None:
                text = '*Swapper*'
                friends = FriendDBHandler().getFriends()
                for friend in friends:
                    #print "SPEW COMPARING friend",show_permid(friend['permid']),"to spew",show_permid(spew[line]['unauth_permid'])
                    if friend['permid'] == spew[line]['unauth_permid']:
                        text = friend['name']
                        break
                return text
            else:
                return ""
        
        return 0
            
    def getSpewColumnText(self, colid, line, spew):
        text = None
        
        starflag = { True : '*', False : ' ' }
        
        if colid == SPEW_UNCHOKE:
            text = starflag[spew[line]['optimistic']]
            
        elif colid == SPEW_IP:
            text = spew[line]['ip']
            
        elif colid == SPEW_LR:
            if spew[line]['direction'] == 'R':
                text = self.utility.lang.get('spew_direction_remote')
            else:
                text = self.utility.lang.get('spew_direction_local')
            
        elif colid == SPEW_UP:
            if spew[line]['uprate'] > 100:
                text = self.utility.speed_format(spew[line]['uprate'], truncate = 0, stopearly = "KB")
            
            
        elif colid == SPEW_INTERESTED:
            text = starflag[spew[line]['uinterested']]
            
        elif colid == SPEW_CHOKING:
            text = starflag[spew[line]['uchoked']]
            
        elif colid == SPEW_DOWN:
            if spew[line]['downrate'] > 100:
                text = self.utility.speed_format(spew[line]['downrate'], truncate = 0, stopearly = "KB")
            
        elif colid == SPEW_INTERESTING:
            text = starflag[spew[line]['dinterested']]
            
        elif colid == SPEW_CHOKED:
            text = starflag[spew[line]['dchoked']]
            
        elif colid == SPEW_SNUBBED:
            text = starflag[spew[line]['snubbed']]
            
        elif colid == SPEW_DLSIZE:
            text = self.utility.size_format(float(spew[line]['dtotal']))
            
        elif colid == SPEW_ULSIZE:
            if spew[line]['utotal'] is not None:
                text = self.utility.size_format(float(spew[line]['utotal']))
                
        elif colid == SPEW_PEERPROGRESS:
            text = '%.1f%%' % (float(int(spew[line]['completed']*1000))/10)
            
        elif colid == SPEW_PEERSPEED:
            if spew[line]['speed'] is not None:
                text = self.utility.speed_format(spew[line]['speed'], truncate = 0)

        elif colid == SPEW_PERMID:
            if spew[line]['unauth_permid'] is not None:
                text = '*Swapper*'
                friends = FriendDBHandler().getFriends()
                for friend in friends:
                    #print "SPEW COMPARING friend",show_permid(friend['permid']),"to spew",show_permid(spew[line]['unauth_permid'])
                    if friend['permid'] == spew[line]['unauth_permid']:
                        text = friend['name']
                        break
            
        if text is None:
            text = ""
            
        return text

    def errormsg(self, errormsg):
        errors = {"problem connecting to tracker": self.utility.lang.get('trackererror_problemconnecting'), 
                  "rejected by tracker": self.utility.lang.get('trackererror_rejected'), 
                  "bad data from tracker": self.utility.lang.get('trackererror_baddata') }
        
        try:
            trackererror = False

            for error in errors:
                index = errormsg.lower().find(error)
                if index != -1:
                    oldlen = len(error)
                    errormsg = errormsg[:index] + errors[error] + errormsg[index + oldlen:]
                    trackererror = True
                    break
            if trackererror:
                currenttime = time()
                if self.lasterrortracker == 0:
                    self.lasterrortracker = currenttime

                if (currenttime - self.lasterrortracker) < 120: #error with in 2 mins
                    self.numerrortracker += 1
                else:
                    self.numerrortracker = 0
                self.lasterrortracker = currenttime
        except:
            pass
        
        self.errormsgCallback(errormsg, "error")

        # If failed connecting tracker in parameter 'timeouttracker' mins
        # reduce its priority and force to queue
        ################################################################
        if self.torrent.connection.timeout and self.utility.config.Read('timeouttracker') != "oo":
            try:
                if self.numerrortracker > self.utility.config.Read('timeouttracker', "int"):
                    self.ReducePrioandForceQueue()
            except:
                pass

    def errormsgCallback(self,msg,label):
        self.invokeLater(self.onErrorMsg,[msg,label])

    def onErrorMsg(self,msg,label):
        self.torrent.changeMessage(msg, label)

    def ReducePrioandForceQueue(self):
        currentprio = self.torrent.prio
        if currentprio < 4:      #prio is not lowest
            self.changePriority(currentprio + 1)     #lower 1 prio

        self.queueMe()

    def changePriority(self,prio):
        self.invokeLater(self.torrent.changePriority,[prio])

    def countSeedingTime(self):
        now = time()
        if self.seedingtimelastcheck is None:
            lastcheck = now
        else:
            lastcheck = self.seedingtimelastcheck
        timelapse = now - lastcheck
        
        self.torrent.connection.seedingtime += timelapse
        
        if self.torrent.connection.getSeedOption('uploadoption') == "1":
            self.torrent.connection.seedingtimeleft = self.torrent.connection.getTargetSeedingTime() - self.torrent.connection.seedingtime
        elif self.torrent.connection.getSeedOption('uploadoption') == "2":
            if self.meanrate['up'] > 0:
                if self.torrent.files.downsize == 0.0 : 
                    down = self.torrent.files.floattotalsize
                else:
                    down = self.torrent.files.downsize
                up = self.torrent.files.upsize
                ratio = float(self.torrent.connection.getSeedOption('uploadratio'))
                required = ((ratio / 100.0) * down) - up
                newseedingtimeleft = required / self.meanrate['up']
                delta = max(newseedingtimeleft/10, 2)
                if abs(self.torrent.connection.seedingtimeleft - newseedingtimeleft) > delta:
                    # If timer value deviates from theoretical value by more then 10%, reset it to theoretical value
                    self.torrent.connection.seedingtimeleft = newseedingtimeleft
                else:
                    # Keep on timing
                    self.torrent.connection.seedingtimeleft -= timelapse
                if self.torrent.connection.seedingtimeleft < 0.1:
                    self.torrent.connection.seedingtimeleft = 0.1
            else:
                # Set to 366 days (= infinite)
                self.torrent.connection.seedingtimeleft = 999999999999999

        self.seedingtimelastcheck = now

    def TerminateUpload(self):
        # Terminate process
        ####################################################
        # change:   5:Progress  6:BT Status
        # clear : 8:ETA 10:DLSpeed 11:ULspeed
        #         14:#seed 15:#peer 16:#copie 17:peer avg
        #         20:total speed
        #####################################################
        self.torrent.status.completed = True
        self.progress = 100.0

        self.torrent.connection.stopEngine()
        
        self.queue.updateAndInvoke()

    def finished(self):
        # Let main thread perform GUI updates
        self.invokeLater(self.finished_callback)

    def finished_callback(self):
        self.seed = True
        
        # seeding process
        ####################################################
        # change:   5:Progress  6:BT Status
        # clear :   8:ETA 10:DLSpeed  
        #####################################################
        self.torrent.status.completed = True
        self.progress = 100.0
        self.torrent.files.updateProgress()

        self.stop_download_help()

        if self.torrent.status.isDoneUploading():
            self.TerminateUpload()
        
        # Update cols 5, 6, 8, 10
        self.torrent.updateColumns([COL_PROGRESS, 
                                    COL_BTSTATUS, 
                                    COL_ETA, 
                                    COL_DLSPEED])
        self.torrent.updateColor()

        self.queue.updateAndInvoke()
            
    def failed(self):
        if self.utility.config.Read('failbehavior') == '0':
            # Stop      
            self.actionhandlerCallback( STATUS_STOP, self.torrent )
        else:
            # Queue
            self.queueMe()
                

    # Only queue if other things are waiting
    # that would start up by queuing this torrent
    def queueMe(self):       
        # See what the next torrent to start would be if we queued
        # this torrent
        inactivetorrents = self.utility.queue.getInactiveTorrents(1)
        if not inactivetorrents:
            return
        
        nexttorrent = inactivetorrents[0]
        
        # See if this torrent would be started if queued
        queuethis = False
        if (nexttorrent.prio < self.torrent.prio):
            queuethis = True
        elif (nexttorrent.prio == self.torrent.prio) and (nexttorrent.listindex < self.torrent.listindex):
            queuethis = True

        if queuethis:
            self.btstatus = self.utility.lang.get('queue')
            self.actionhandlerCallback( STATUS_QUEUE, self.torrent )

    def actionhandlerCallback(self,action,torrent):
        self.invokeLater(self.onActionhandler,[action,torrent])

    def onActionhandler(self,action,torrent):
        """ as calls to procQUEUE and procSTOP are usually by event handlers
            executed by the mainthread, let the mainthread call them here as well
            to prevent GUI update problems.
        """
        if action == STATUS_QUEUE:
            self.utility.actionhandler.procQUEUE([torrent])
        else:
            self.utility.actionhandler.procSTOP([torrent])

    def getDownloadhelpCoordinator(self):
        return self.dow.coordinator

    def stop_download_help(self):
        if self.dow.coordinator is not None:
            self.dow.coordinator.stop_all_help()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.