Tribler: status message are written into a file, instead of stderr
authorAdriana Draghici <adriana008@gmail.com>
Fri, 27 Nov 2009 13:11:13 +0000 (13:11 +0000)
committerAdriana Draghici <adriana008@gmail.com>
Fri, 27 Nov 2009 13:11:13 +0000 (13:11 +0000)
tribler-mod/SingleDownload.py [new file with mode: 0644]
tribler-mod/Tribler/Core/APIImplementation/SingleDownload.py
tribler-mod/Tribler/Tools/cmdlinedl.py
tribler-mod/cmdlinedl.py
tribler-mod/scripts/README

diff --git a/tribler-mod/SingleDownload.py b/tribler-mod/SingleDownload.py
new file mode 100644 (file)
index 0000000..d13c6c4
--- /dev/null
@@ -0,0 +1,306 @@
+from time import localtime, strftime
+# Written by Arno Bakker 
+# see LICENSE.txt for license information
+
+import sys
+import os
+import time
+import copy
+import sha
+import pickle
+import socket
+import binascii
+from types import StringType,ListType,IntType
+from traceback import print_exc,print_stack
+from threading import Event
+
+from Tribler.Core.simpledefs import *
+from Tribler.Core.exceptions import *
+from Tribler.Core.BitTornado.__init__ import createPeerID
+from Tribler.Core.BitTornado.download_bt1 import BT1Download
+from Tribler.Core.BitTornado.bencode import bencode,bdecode
+from Tribler.Core.Video.VideoStatus import VideoStatus
+
+
+SPECIAL_VALUE = 481
+
+DEBUG = True  #False
+
+
+# Transfers' status info is output into status_file.
+FILE_NAME = "status_msg.log" #+ strftime("_%d_%b_%Y_%H_%M_%S", localtime()) + ".log"
+status_file = open(FILE_NAME, 'w');
+
+class SingleDownload:
+    """ This class is accessed solely by the network thread """
+    
+    def __init__(self,infohash,metainfo,kvconfig,multihandler,get_extip_func,listenport,videoanalyserpath,vodfileindex,set_error_func,pstate,lmvodeventcallback,lmhashcheckcompletecallback):
+        
+        self.dow = None
+        self.set_error_func = set_error_func
+        self.videoinfo = None
+        self.videostatus = None
+        self.lmvodeventcallback = lmvodeventcallback
+        self.lmhashcheckcompletecallback = lmhashcheckcompletecallback
+        self.logmsgs = []
+        self._hashcheckfunc = None
+        self._getstatsfunc = None
+        try:
+            self.dldoneflag = Event()
+            self.dlrawserver = multihandler.newRawServer(infohash,self.dldoneflag)
+            self.lmvodeventcallback = lmvodeventcallback
+    
+            if pstate is not None:
+                self.hashcheckfrac = pstate['dlstate']['progress']
+            else:
+                self.hashcheckfrac = 0.0
+    
+            self.peerid = createPeerID()
+            #print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: __init__: My peer ID is",`peerid`
+    
+            self.dow = BT1Download(self.hashcheckprogressfunc,
+                            self.finishedfunc,
+                            self.fatalerrorfunc, 
+                            self.nonfatalerrorfunc,
+                            self.logerrorfunc,
+                            self.dldoneflag,
+                            kvconfig,
+                            metainfo, 
+                            infohash,
+                            self.peerid,
+                            self.dlrawserver,
+                            get_extip_func,
+                            listenport,
+                            videoanalyserpath
+                            )
+        
+            file = self.dow.saveAs(self.save_as)
+            #if DEBUG:
+            #    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: dow.saveAs returned",file
+            
+            # Set local filename in vodfileindex
+            if vodfileindex is not None:
+                index = vodfileindex['index']
+                if index == -1:
+                    index = 0
+                vodfileindex['outpath'] = self.dow.get_dest(index)
+                self.videoinfo = vodfileindex
+                if 'live' in metainfo['info']:
+                    authparams = metainfo['info']['live']
+                else:
+                    authparams = None
+                self.videostatus = VideoStatus(metainfo['info']['piece length'],self.dow.files,vodfileindex,authparams)
+                self.videoinfo['status'] = self.videostatus
+                self.dow.set_videoinfo(vodfileindex,self.videostatus)
+
+            #if DEBUG:
+            #    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: setting vodfileindex",vodfileindex
+            
+            if pstate is None:
+                resumedata = None
+            else:
+                # Restarting download
+                resumedata=pstate['engineresumedata']
+            self._hashcheckfunc = self.dow.initFiles(resumedata=resumedata)
+            
+            
+        except Exception,e:
+            self.fatalerrorfunc(e)
+    
+    def get_bt1download(self):
+        return self.dow
+    
+    def save_as(self,name,length,saveas,isdir):
+        """ Return the local filename to which to save the file 'name' in the torrent """
+        if DEBUG:
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: save_as(",`name`,length,`saveas`,isdir,")"
+           # status_file.close()
+        try:
+            if not os.access(saveas,os.F_OK):
+                os.mkdir(saveas)
+            path = os.path.join(saveas,name)
+            if isdir and not os.path.isdir(path):
+                os.mkdir(path)
+            return path
+        except Exception,e:
+            self.fatalerrorfunc(e)
+
+    def perform_hashcheck(self,complete_callback):
+        """ Called by any thread """
+        if DEBUG:
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: perform_hashcheck()" # ,self.videoinfo
+            #status_file.close()
+        try:
+            """ Schedules actually hashcheck on network thread """
+            self._getstatsfunc = SPECIAL_VALUE # signal we're hashchecking
+            # Already set, should be same
+            self.lmhashcheckcompletecallback = complete_callback
+            self._hashcheckfunc(self.lmhashcheckcompletecallback)
+        except Exception,e:
+            self.fatalerrorfunc(e)
+            
+    def hashcheck_done(self):
+        """ Called by LaunchMany when hashcheck complete and the Download can be
+            resumed
+            
+            Called by network thread
+        """
+        if DEBUG:
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: hashcheck_done()"
+        try:
+            self.dow.startEngine(vodeventfunc = self.lmvodeventcallback)
+            self._getstatsfunc = self.dow.startStats() # not possible earlier
+            self.dow.startRerequester()
+            self.dlrawserver.start_listening(self.dow.getPortHandler())
+        except Exception,e:
+            self.fatalerrorfunc(e)
+
+
+    # DownloadConfigInterface methods
+    def set_max_speed(self,direct,speed,callback):
+        if self.dow is not None:
+            if DEBUG:
+                print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: set_max_speed",`self.dow.response['info']['name']`,direct,speed
+            if direct == UPLOAD:
+                self.dow.setUploadRate(speed,networkcalling=True)
+            else:
+                self.dow.setDownloadRate(speed,networkcalling=True)
+        if callback is not None:
+            callback(direct,speed)
+
+    def set_max_conns_to_initiate(self,nconns,callback):
+        if self.dow is not None:
+            if DEBUG:
+                print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: set_max_conns_to_initiate",`self.dow.response['info']['name']`,direct,speed
+            self.dow.setInitiate(nconns,networkcalling=True)
+        if callback is not None:
+            callback(nconns)
+
+
+    def set_max_conns(self,nconns,callback):
+        if self.dow is not None:
+            if DEBUG:
+                print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: set_max_conns",`self.dow.response['info']['name']`,direct,speed
+            self.dow.setMaxConns(nconns,networkcalling=True)
+        if callback is not None:
+            callback(nconns)
+
+
+    #
+    # For DownloadState
+    #
+    def get_stats(self,getpeerlist):
+        logmsgs = self.logmsgs[:] # copy
+        coopdl_helpers = []
+        coopdl_coordinator = None
+        if self.dow is not None:
+            if not self.dow.helper is None:
+                coopdl_coordinator = self.dow.helper.get_coordinator_permid() 
+            if self.dow.coordinator is not None: 
+                # No coordinator when you're a helper
+                peerreclist = self.dow.coordinator.network_get_asked_helpers_copy()
+                for peerrec in peerreclist:
+                    coopdl_helpers.append(peerrec['permid'])
+        if self._getstatsfunc is None:
+            return (DLSTATUS_WAITING4HASHCHECK,None,logmsgs,coopdl_helpers,coopdl_coordinator)
+        elif self._getstatsfunc == SPECIAL_VALUE:
+            stats = {}
+            stats['frac'] = self.hashcheckfrac
+            return (DLSTATUS_HASHCHECKING,stats,logmsgs,coopdl_helpers,coopdl_coordinator)
+        else:
+            return (None,self._getstatsfunc(getpeerlist=getpeerlist),logmsgs,coopdl_helpers,coopdl_coordinator)
+
+    def get_infohash(self):
+        return self.infohash
+
+    #
+    # Persistent State
+    #
+    def checkpoint(self):
+        if self.dow is not None:
+            return self.dow.checkpoint()
+        else:
+            return None
+    
+    def shutdown(self):
+        if DEBUG:
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: shutdown"
+            #status_file.close()
+        resumedata = None
+        if self.dow is not None:
+            self.dldoneflag.set()
+            self.dlrawserver.shutdown()
+            resumedata = self.dow.shutdown()
+            self.dow = None
+            #if DEBUG:
+            #    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: stopped dow"
+                
+        if self._getstatsfunc is None or self._getstatsfunc == SPECIAL_VALUE:
+            # Hashchecking or waiting for while being shutdown, signal LaunchMany
+            # so it can schedule a new one.
+            self.lmhashcheckcompletecallback(success=False)
+        return resumedata
+
+    #
+    # Cooperative download
+    #
+    def ask_coopdl_helpers(self,peerreclist):
+        if self.dow is not None:
+            self.dow.coordinator.network_request_help(peerreclist)
+
+    def stop_coopdl_helpers(self,peerreclist):
+        if self.dow is not None:
+            self.dow.coordinator.network_stop_help(peerreclist,force=True)
+
+    def get_coopdl_role_object(self,role):
+        # Used by Coordinator/HelperMessageHandler indirectly
+        if self.dow is not None:
+            if role == COOPDL_ROLE_COORDINATOR:
+                return self.dow.coordinator
+            else:
+                return self.dow.helper
+        else:
+            return None
+
+    #
+    # Internal methods
+    #
+    def hashcheckprogressfunc(self,activity = '', fractionDone = 0.0):
+        """ Allegedly only used by StorageWrapper during hashchecking """
+        #print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::statusfunc called",activity,fractionDone
+        self.hashcheckfrac = fractionDone
+
+    def finishedfunc(self):
+        """ Download is complete """
+        if DEBUG:
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::finishedfunc called: Download is complete *******************************"
+            #status_file.close()
+        pass
+
+    def fatalerrorfunc(self,data):
+        print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::fatalerrorfunc called",data
+        if type(data) == StringType:
+            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","LEGACY CORE FATAL ERROR",data
+            print_stack()
+            self.set_error_func(TriblerLegacyException(data))
+        else:
+            print_exc()
+            self.set_error_func(data)
+        self.shutdown()
+
+    def nonfatalerrorfunc(self,e):
+        print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::nonfatalerrorfunc called",e
+        # Could log this somewhere, or phase it out (only used in Rerequester)
+
+    def logerrorfunc(self,msg):
+        t = time.time()
+        self.logmsgs.append((t,msg))
+        
+        # Keep max 10 log entries, API user should save them if he wants 
+        # complete history
+        if len(self.logmsgs) > 10:
+            self.logmsgs.pop(0)
+            
index 6e644f2..d13c6c4 100644 (file)
@@ -1,4 +1,7 @@
 from time import localtime, strftime
 # Written by Arno Bakker 
 # see LICENSE.txt for license information
 
@@ -26,6 +29,11 @@ SPECIAL_VALUE = 481
 
 DEBUG = True  #False
 
+
+# Transfers' status info is output into status_file.
+FILE_NAME = "status_msg.log" #+ strftime("_%d_%b_%Y_%H_%M_%S", localtime()) + ".log"
+status_file = open(FILE_NAME, 'w');
+
 class SingleDownload:
     """ This class is accessed solely by the network thread """
     
@@ -108,7 +116,8 @@ class SingleDownload:
     def save_as(self,name,length,saveas,isdir):
         """ Return the local filename to which to save the file 'name' in the torrent """
         if DEBUG:
-            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: save_as(",`name`,length,`saveas`,isdir,")"
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: save_as(",`name`,length,`saveas`,isdir,")"
+           # status_file.close()
         try:
             if not os.access(saveas,os.F_OK):
                 os.mkdir(saveas)
@@ -122,7 +131,8 @@ class SingleDownload:
     def perform_hashcheck(self,complete_callback):
         """ Called by any thread """
         if DEBUG:
-            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: perform_hashcheck()" # ,self.videoinfo
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: perform_hashcheck()" # ,self.videoinfo
+            #status_file.close()
         try:
             """ Schedules actually hashcheck on network thread """
             self._getstatsfunc = SPECIAL_VALUE # signal we're hashchecking
@@ -139,7 +149,7 @@ class SingleDownload:
             Called by network thread
         """
         if DEBUG:
-            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: hashcheck_done()"
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: hashcheck_done()"
         try:
             self.dow.startEngine(vodeventfunc = self.lmvodeventcallback)
             self._getstatsfunc = self.dow.startStats() # not possible earlier
@@ -217,7 +227,8 @@ class SingleDownload:
     
     def shutdown(self):
         if DEBUG:
-            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: shutdown"
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload: shutdown"
+            #status_file.close()
         resumedata = None
         if self.dow is not None:
             self.dldoneflag.set()
@@ -265,7 +276,8 @@ class SingleDownload:
     def finishedfunc(self):
         """ Download is complete """
         if DEBUG:
-            print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::finishedfunc called: Download is complete *******************************"
+            print >>status_file, strftime("%d-%m-%Y %H:%M:%S", localtime())," ","SingleDownload::finishedfunc called: Download is complete *******************************"
+            #status_file.close()
         pass
 
     def fatalerrorfunc(self,data):
index 2649edd..0911d0b 100644 (file)
@@ -1,5 +1,4 @@
 from time import localtime, strftime
-from time import localtime, strftime
 
 # Written by Arno Bakker 
 # see LICENSE.txt for license information
@@ -22,6 +21,10 @@ from Tribler.Core.API import *
 from Tribler.Core.BitTornado.__init__ import version, report_email
 
 
+# Transfers' status info is output into status_file.
+FILE_NAME = "status_msg.log" #+ strftime("_%d_%b_%Y_%H_%M_%S", localtime()) + ".log"
+status_file = open(FILE_NAME, 'w');
+
 def usage():
     print "Usage: python cmdlinedl.py [options] torrent_file"
     print "Options:"
@@ -38,13 +41,17 @@ def usage():
     print
     print "Report bugs to <" + report_email + ">"
 
+
 def print_version():
     print version, "<" + report_email + ">"
 
+
+
+
 def state_callback(ds):
     d = ds.get_download()
-#    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ", strftime("%d %b %Y %H:%M:%S", localtime())," ",`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD)
-    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ", strftime("%d %b %Y %H:%M:%S", localtime())," ", '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s eta %d peers %d' % \
+#    print >>sys.stderr, strftime("%d %b %Y %H:%M:%S", localtime())," ",`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD)
+    print >>status_file, strftime("%d %b %Y %H:%M:%S", localtime())," ", '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s eta %d peers %d' % \
             (d.get_def().get_name(), \
             dlstatus_strings[ds.get_status()], \
             ds.get_progress() * 100, \
@@ -137,3 +144,4 @@ def main():
 
 if __name__ == "__main__":
     main()
+    status_file.close();
index 2649edd..0911d0b 100644 (file)
@@ -1,5 +1,4 @@
 from time import localtime, strftime
-from time import localtime, strftime
 
 # Written by Arno Bakker 
 # see LICENSE.txt for license information
@@ -22,6 +21,10 @@ from Tribler.Core.API import *
 from Tribler.Core.BitTornado.__init__ import version, report_email
 
 
+# Transfers' status info is output into status_file.
+FILE_NAME = "status_msg.log" #+ strftime("_%d_%b_%Y_%H_%M_%S", localtime()) + ".log"
+status_file = open(FILE_NAME, 'w');
+
 def usage():
     print "Usage: python cmdlinedl.py [options] torrent_file"
     print "Options:"
@@ -38,13 +41,17 @@ def usage():
     print
     print "Report bugs to <" + report_email + ">"
 
+
 def print_version():
     print version, "<" + report_email + ">"
 
+
+
+
 def state_callback(ds):
     d = ds.get_download()
-#    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ", strftime("%d %b %Y %H:%M:%S", localtime())," ",`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD)
-    print >>sys.stderr, strftime("%d-%m-%Y %H:%M:%S", localtime())," ", strftime("%d %b %Y %H:%M:%S", localtime())," ", '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s eta %d peers %d' % \
+#    print >>sys.stderr, strftime("%d %b %Y %H:%M:%S", localtime())," ",`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD)
+    print >>status_file, strftime("%d %b %Y %H:%M:%S", localtime())," ", '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s eta %d peers %d' % \
             (d.get_def().get_name(), \
             dlstatus_strings[ds.get_status()], \
             ds.get_progress() * 100, \
@@ -137,3 +144,4 @@ def main():
 
 if __name__ == "__main__":
     main()
+    status_file.close();
index 5854c2a..e9f3062 100644 (file)
@@ -30,5 +30,8 @@ Fisierele modified_files_* contin pe fiecare linie calea catre un fisier ce treb
 Liniile care nu contin cel putin un "/" sunt ignorate.
 
 ======= 
-
-Fisierul cmdlinedl.py este modificat pt a afisa eta si numarul de peers.
+Fisiere modificate "de mana":
+ - cmdlinedl.py este modificat - pt a afisa eta si numarul de peers.
+                                                          - pt a scrie intr-un fisier "status_msg.log" in loc de stderr
+ - Core/APIImplementation/SingleDownload.py - pt a scrie informatii de status in fisierul "status_msg.log" in loc de stderr
+