| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 |
- #!/usr/bin/env python
- ################################################################################
- # $Id: tfmainline.py 2535 2007-02-06 22:20:57Z b4rt $
- # $Revision: 2535 $
- # $Date: 2007-02-06 16:20:57 -0600 (Tue, 06 Feb 2007) $
- ################################################################################
- #
- # The contents of this file are subject to the BitTorrent Open Source License
- # Version 1.1 (the License). You may not copy or use this file, in either
- # source code or executable form, except in compliance with the License. You
- # may obtain a copy of the License at http://www.bittorrent.com/license/.
- #
- # Software distributed under the License is distributed on an AS IS basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # Written by Bram Cohen, Uoti Urpala, John Hoffman, and David Harrison
- #
- ################################################################################
- #
- # tfmainline.py - use BitTorrent ("mainline") with torrentflux-b4rt
- # http://tf-b4rt.berlios.de/
- #
- ################################################################################
- from __future__ import division
- app_name = "BitTorrent"
- from BitTorrent.translation import _
- import sys
- import os
- from os import getpid, remove
- from os.path import isfile
- from cStringIO import StringIO
- import logging
- from logging import ERROR, WARNING
- from time import strftime, sleep
- import traceback
- import BTL.stackthreading as threading
- from BTL.platform import decode_from_filesystem, encode_for_filesystem
- from BitTorrent.platform import get_dot_dir
- from BTL.defer import DeferredEvent
- from BitTorrent import inject_main_logfile
- from BitTorrent.MultiTorrent import Feedback, MultiTorrent
- from BitTorrent.defaultargs import get_defaults
- from BitTorrent.parseargs import printHelp
- from BitTorrent.prefs import Preferences
- from BitTorrent import configfile
- from BitTorrent import BTFailure, UserFailure
- from BitTorrent import version
- from BitTorrent import GetTorrent
- from BTL.ConvertedMetainfo import ConvertedMetainfo
- from BitTorrent.MultiTorrent import TorrentNotInitialized
- from BitTorrent.RawServer_twisted import RawServer
- from twisted.internet import task
- from BitTorrent.UI import Size, Duration
- inject_main_logfile()
- from BitTorrent import console
- from BitTorrent import stderr_console
- def wrap_log(context_string, logger):
- """Useful when passing a logger to a deferred's errback. The context
- specifies what was being done when the exception was raised."""
- return lambda e, *args, **kwargs : logger.error(context_string, exc_info=e)
- def fmtsize(n):
- s = str(n)
- size = s[-3:]
- while len(s) > 3:
- s = s[:-3]
- size = '%s,%s' % (s[-3:], size)
- size = '%s (%s)' % (size, str(Size(n)))
- return size
- #------------------------------------------------------------------------------#
- # tfb static methods #
- #------------------------------------------------------------------------------#
- def fmttime(n):
- """ fmttime """
- # short format :
- return fmttimeshort(n)
- # long format :
- # return fmttimelong(n)
- def fmttimeshort(n):
- """ fmttimeshort """
- if n == 0:
- return 'complete!'
- try:
- n = int(n)
- assert n >= 0 and n < 5184000 # 60 days
- except:
- return '<unknown>'
- m, s = divmod(n, 60)
- h, m = divmod(m, 60)
- d, h = divmod(h, 24)
- if d >= 7:
- return '-'
- elif d > 0:
- return '%dd %02d:%02d:%02d' % (d, h, m, s)
- else:
- return '%02d:%02d:%02d' % (h, m, s)
- def fmttimelong(n):
- """ fmttimelong """
- if n == 0:
- return 'complete!'
- try:
- n = int(n)
- assert n >= 0 and n < 5184000 # 60 days
- except:
- return '<unknown>'
- m, s = divmod(n, 60)
- h, m = divmod(m, 60)
- d, h = divmod(h, 24)
- y, d = divmod(d, 365)
- dec, y = divmod(y, 10)
- cent, dec = divmod(dec, 10)
- if cent > 0:
- return '%dcent %ddec %dy %dd %02d:%02d:%02d' % (cent, dec, y, d, h, m, s)
- elif dec > 0:
- return '%ddec %dy %dd %02d:%02d:%02d' % (dec, y, d, h, m, s)
- elif y > 0:
- return '%dy %dd %02d:%02d:%02d' % (y, d, h, m, s)
- elif d > 0:
- return '%dd %02d:%02d:%02d' % (d, h, m, s)
- else:
- return '%02d:%02d:%02d' % (h, m, s)
- def transferLog(message, ts):
- """ transferLog """
- try:
- FILE = open(transferLogFile,"a+")
- if not ts:
- FILE.write(message)
- else:
- FILE.write(strftime('[%Y/%m/%d - %H:%M:%S]') + " " + message)
- FILE.flush()
- FILE.close()
- except Exception, e:
- sys.stderr.write("Failed to write log-file : " + transferLogFile + "\n")
- #------------------------------------------------------------------------------#
- # HeadlessDisplayer #
- #------------------------------------------------------------------------------#
- class HeadlessDisplayer(object):
- def __init__(self):
- self.done = False
- self.state = 1
- self.percentDone = ''
- self.timeEst = ''
- self.downRate = '---'
- self.upRate = '---'
- self.shareRating = ''
- self.seedStatus = ''
- self.peerStatus = ''
- self.errors = []
- self.file = ''
- self.downloadTo = ''
- self.fileSize = ''
- self.fileSize_stat = ''
- self.numpieces = 0
- self.tfOwner = config['tf_owner']
- self.seedLimit = config['seed_limit']
- self.dieWhenDone = config['die_when_done']
- self.isInShutDown = 0
- self.running = '1'
- self.displayCounter = 0
- def set_torrent_values(self, name, path, size, numpieces):
- self.file = name
- self.downloadTo = path
- self.fileSize = fmtsize(size)
- self.fileSize_stat = int(size)
- self.numpieces = numpieces
- def finished(self):
- """ this method is never called """
- self.done = True
- self.downRate = '---'
- self.display({'activity':_("download succeeded"), 'fractionDone':1})
- def error(self, errormsg):
- self.errors.append(errormsg)
- # log error
- transferLog("error: " + errormsg + "\n", True)
- def display(self, statistics):
- # only process when not in shutdown-sequence
- if self.isInShutDown == 0:
- # eta
- activity = statistics.get('activity')
- timeEst = statistics.get('timeEst')
- if timeEst is not None:
- self.timeEst = fmttime(timeEst)
- elif activity is not None:
- self.timeEst = activity
- # fractionDone
- fractionDone = statistics.get('fractionDone')
- if fractionDone is not None:
- self.percentDone = str(int(fractionDone * 1000) / 10)
- # downRate
- downRate = statistics.get('downRate')
- if downRate is not None:
- self.downRate = '%.1f kB/s' % (downRate / (1 << 10))
- # upRate
- upRate = statistics.get('upRate')
- if upRate is not None:
- self.upRate = '%.1f kB/s' % (upRate / (1 << 10))
- # totals
- downTotal = statistics.get('downTotal')
- upTotal = statistics.get('upTotal')
- if upTotal is None:
- upTotal = 0
- if downTotal is None:
- downTotal = 0
- # share-rating
- if downTotal > 0:
- if upTotal > 0:
- self.shareRating = _("%.3f") % ((upTotal * 100) / downTotal)
- else:
- self.shareRating = "0"
- else:
- self.shareRating = "oo"
- # seeds
- seeds = statistics.get('numSeeds')
- if seeds is None:
- seeds = 0
- # dht :
- numCopies = statistics.get('numCopies')
- if numCopies is not None:
- seeds += numCopies
- # set status
- self.seedStatus = _("%d") % seeds
- # peers
- peers = statistics.get('numPeers')
- if peers is not None:
- self.peerStatus = _("%d") % peers
- else:
- self.peerStatus = "0"
- # set some fields in app which we need in shutdown
- app.percentDone = self.percentDone
- app.shareRating = self.shareRating
- app.upTotal = upTotal
- app.downTotal = downTotal
- # process command-stack
- die = app.processCommandStack()
- if die:
- # shutdown
- self.execShutdown()
- return;
- # die-on-seed-limit / die-when-done
- if app.multitorrent.isDone:
- if self.dieWhenDone == 'True':
- transferLog("die-when-done set, setting shutdown-flag...\n", True)
- die = True
- else:
- seedLimitMax = int(self.seedLimit)
- if seedLimitMax > 0:
- totalShareRating = int(((upTotal * 100) / self.fileSize_stat))
- if totalShareRating >= seedLimitMax:
- transferLog("seed-limit "+str(self.seedLimit)+" reached, setting shutdown-flag...\n", True)
- die = True
- # shutdown / stat
- if die:
- # shutdown
- self.execShutdown()
- else:
- # write every 5 secs
- if self.displayCounter < 5:
- self.displayCounter += 1
- else:
- self.displayCounter = 0
- # write stat-file
- try:
- FILE = open(transferStatFile, "w")
- FILE.write(repr(self.state)+"\n")
- FILE.write(self.percentDone+"\n")
- FILE.write(self.timeEst+"\n")
- FILE.write(self.downRate+"\n")
- FILE.write(self.upRate+"\n")
- FILE.write(self.tfOwner+"\n")
- FILE.write(self.seedStatus+"\n")
- FILE.write(self.peerStatus+"\n")
- FILE.write(self.shareRating+"\n")
- FILE.write(self.seedLimit+"\n")
- FILE.write(repr(upTotal)+"\n")
- FILE.write(repr(downTotal)+"\n")
- FILE.write(repr(self.fileSize_stat))
- FILE.flush()
- FILE.close()
- except Exception, e:
- transferLog("Failed to write stat-file : " + transferStatFile + "\n", True)
- def execShutdown(self):
- """ execShutdown """
- # log
- transferLog("mainline shutting down...\n", True)
- # set flags
- self.state = 0
- self.isInShutDown = 1
- self.running = '0'
- # shutdown
- df = app.multitorrent.shutdown()
- stop_rawserver = lambda *a : app.multitorrent.rawserver.stop()
- df.addCallbacks(stop_rawserver, stop_rawserver)
- def print_spew(self, spew):
- s = StringIO()
- s.write('\n\n\n')
- for c in spew:
- s.write('%20s ' % c['ip'])
- if c['initiation'] == 'L':
- s.write('l')
- else:
- s.write('r')
- total, rate, interested, choked = c['upload']
- s.write(' %10s %10s ' % (str(int(total/10485.76)/100),
- str(int(rate))))
- if c['is_optimistic_unchoke']:
- s.write('*')
- else:
- s.write(' ')
- if interested:
- s.write('i')
- else:
- s.write(' ')
- if choked:
- s.write('c')
- else:
- s.write(' ')
- total, rate, interested, choked, snubbed = c['download']
- s.write(' %10s %10s ' % (str(int(total/10485.76)/100),
- str(int(rate))))
- if interested:
- s.write('i')
- else:
- s.write(' ')
- if choked:
- s.write('c')
- else:
- s.write(' ')
- if snubbed:
- s.write('s')
- else:
- s.write(' ')
- s.write('\n')
- print s.getvalue()
- #------------------------------------------------------------------------------#
- # TorrentApp #
- #------------------------------------------------------------------------------#
- class TorrentApp(object):
- class LogHandler(logging.Handler):
- def __init__(self, app, level=logging.NOTSET):
- logging.Handler.__init__(self,level)
- self.app = app
- def emit(self, record):
- self.app.display_error(record.getMessage() )
- if record.exc_info is not None:
- self.app.display_error( " %s: %s" %
- ( str(record.exc_info[0]), str(record.exc_info[1])))
- tb = record.exc_info[2]
- stack = traceback.extract_tb(tb)
- l = traceback.format_list(stack)
- for s in l:
- self.app.display_error( " %s" % s )
- class LogFilter(logging.Filter):
- def filter( self, record):
- if record.name == "NatTraversal":
- return 0
- return 1 # allow.
- def __init__(self, metainfo, config):
- assert isinstance(metainfo, ConvertedMetainfo )
- self.metainfo = metainfo
- self.config = Preferences().initWithDict(config)
- self.torrent = None
- self.multitorrent = None
- self.logger = logging.getLogger("bittorrent-console")
- log_handler = TorrentApp.LogHandler(self)
- log_handler.setLevel(WARNING)
- logger = logging.getLogger()
- logger.addHandler(log_handler)
- # some fields we need in shutdown
- self.percentDone = "0"
- self.shareRating = "0"
- self.upTotal = "0"
- self.downTotal = "0"
- # disable stdout and stderr error reporting to stderr.
- global stderr_console
- logging.getLogger('').removeHandler(console)
- if stderr_console is not None:
- logging.getLogger('').removeHandler(stderr_console)
- logging.getLogger().setLevel(WARNING)
- def start_torrent(self,metainfo,save_incomplete_as,save_as):
- """Tells the MultiTorrent to begin downloading."""
- try:
- self.d.display({'activity':_("initializing"), 'fractionDone':0})
- multitorrent = self.multitorrent
- df = multitorrent.create_torrent(metainfo, save_incomplete_as,
- save_as)
- df.addErrback( wrap_log('Failed to start torrent', self.logger))
- def create_finished(torrent):
- self.torrent = torrent
- if self.torrent.is_initialized():
- multitorrent.start_torrent(self.torrent.infohash)
- else:
- # HEREDAVE: why should this set the doneflag?
- self.core_doneflag.set() # e.g., if already downloading...
- df.addCallback( create_finished )
- except KeyboardInterrupt:
- raise
- except UserFailure, e:
- self.logger.error( "Failed to create torrent: " + unicode(e.args[0]) )
- except Exception, e:
- self.logger.error( "Failed to create torrent", exc_info = e )
- return
- def run(self):
- self.core_doneflag = DeferredEvent()
- rawserver = RawServer(self.config)
- self.d = HeadlessDisplayer()
- # set up shut-down procedure before we begin doing things that
- # can throw exceptions.
- def shutdown():
- print "shutdown."
- self.d.display({'activity':_("shutting down"), 'fractionDone':0})
- if self.multitorrent:
- df = self.multitorrent.shutdown()
- stop_rawserver = lambda *a : rawserver.stop()
- df.addCallbacks(stop_rawserver, stop_rawserver)
- else:
- rawserver.stop()
- # write pid-file
- currentPid = (str(getpid())).strip()
- transferLog("writing pid-file : " + transferPidFile + " (" + currentPid + ")\n", True)
- try:
- pidFile = open(transferPidFile, 'w')
- pidFile.write(currentPid + "\n")
- pidFile.flush()
- pidFile.close()
- except Exception, e:
- transferLog("Failed to write pid-file : " + transferPidFile + " (" + currentPid + ")" + "\n", True)
- raise BTFailure(_("Failed to write pid-file."))
- # It is safe to addCallback here, because there is only one thread,
- # but even if the code were multi-threaded, core_doneflag has not
- # been passed to anyone. There is no chance of a race condition
- # between core_doneflag's callback and addCallback.
- self.core_doneflag.addCallback(
- lambda r: rawserver.external_add_task(0, shutdown))
- rawserver.install_sigint_handler(self.core_doneflag)
- # semantics for --save_in vs --save_as:
- # save_in specifies the directory in which torrent is written.
- # If the torrent is a batch torrent then the files in the batch
- # go in save_in/metainfo.name_fs/.
- # save_as specifies the filename for the torrent in the case of
- # a non-batch torrent, and specifies the directory name
- # in the case of a batch torrent. Thus the files in a batch
- # torrent go in save_as/.
- metainfo = self.metainfo
- torrent_name = metainfo.name_fs # if batch then this contains
- # directory name.
- if config['save_as']:
- if config['save_in']:
- raise BTFailure(_("You cannot specify both --save_as and "
- "--save_in."))
- saveas,bad = encode_for_filesystem(config['save_as'])
- if bad:
- raise BTFailure(_("Invalid path encoding."))
- savein = os.path.dirname(os.path.abspath(saveas))
- elif config['save_in']:
- savein,bad = encode_for_filesystem(config['save_in'])
- if bad:
- raise BTFailure(_("Invalid path encoding."))
- saveas = os.path.join(savein,torrent_name)
- else:
- saveas = torrent_name
- if config['save_incomplete_in']:
- save_incomplete_in,bad = \
- encode_for_filesystem(config['save_incomplete_in'])
- if bad:
- raise BTFailure(_("Invalid path encoding."))
- save_incomplete_as = os.path.join(save_incomplete_in,torrent_name)
- else:
- save_incomplete_as = os.path.join(savein,torrent_name)
- data_dir,bad = encode_for_filesystem(config['data_dir'])
- if bad:
- raise BTFailure(_("Invalid path encoding."))
- try:
- self.multitorrent = \
- MultiTorrent(self.config, rawserver, data_dir,
- is_single_torrent = True,
- resume_from_torrent_config = False)
- self.d.set_torrent_values(metainfo.name, os.path.abspath(saveas),
- metainfo.total_bytes, len(metainfo.hashes))
- self.start_torrent(self.metainfo, save_incomplete_as, saveas)
- self.get_status()
- except UserFailure, e:
- self.logger.error( unicode(e.args[0]) )
- rawserver.add_task(0, self.core_doneflag.set)
- except Exception, e:
- self.logger.error( "", exc_info = e )
- rawserver.add_task(0, self.core_doneflag.set)
- # log that we are done with startup
- transferLog("mainline up and running.\n", True)
- # always make sure events get processed even if only for
- # shutting down.
- rawserver.listen_forever()
- # overwrite stat-file in "Torrent Stopped"/"Download Succeeded!" format.
- try:
- FILE = open(transferStatFile, "w")
- FILE.write("0\n")
- pcts = "-"+self.percentDone
- pctf = float(pcts)
- pctf -= 100
- FILE.write(str(pctf))
- FILE.write("\n")
- if self.multitorrent.isDone:
- FILE.write("Download Succeeded!\n")
- else:
- FILE.write("Torrent Stopped\n")
- FILE.write("\n")
- FILE.write("\n")
- FILE.write(self.d.tfOwner+"\n")
- FILE.write("\n")
- FILE.write("\n")
- FILE.write(self.shareRating+"\n")
- FILE.write(self.d.seedLimit+"\n")
- FILE.write(repr(self.upTotal)+"\n")
- FILE.write(repr(self.downTotal)+"\n")
- FILE.write(repr(self.d.fileSize_stat))
- FILE.flush()
- FILE.close()
- except Exception, e:
- transferLog("Failed to write stat-file : " + transferStatFile + "\n", True)
- def get_status(self):
- self.multitorrent.rawserver.add_task(self.config['display_interval'],
- self.get_status)
- if self.torrent is not None:
- status = self.torrent.get_status(self.config['spew'])
- self.d.display(status)
- def display_error(self, text):
- """Called by the logger via LogHandler to display error messages in the
- curses window."""
- self.d.error(text)
- def processCommandStack(self):
- """ processCommandStack """
- if isfile(transferCommandFile):
- # process file
- transferLog("Processing command-file " + transferCommandFile + "...\n", True)
- try:
- # read file to mem
- f = open(transferCommandFile, 'r')
- commands = f.readlines()
- f.close
- # remove file
- try:
- remove(transferCommandFile)
- except:
- transferLog("Failed to remove command-file : " + transferCommandFile + "\n", True)
- pass
- # exec commands
- if len(commands) > 0:
- for command in commands:
- command = command.replace("\n", "")
- if len(command) > 0:
- # exec, early out when reading a quit-command
- if self.execCommand(command):
- return True
- else:
- transferLog("No commands found.\n", True)
- except:
- transferLog("Failed to read command-file : " + transferCommandFile + "\n", True)
- pass
- return False
- def execCommand(self, command):
- """ execCommand """
- opCode = command[0]
- # q
- if opCode == 'q':
- transferLog("command: stop-request, setting shutdown-flag...\n", True)
- return True
- # u
- elif opCode == 'u':
- if len(command) < 2:
- transferLog("invalid rate.\n", True)
- return False
- rateNew = command[1:]
- transferLog("command: setting upload-rate to " + rateNew + "...\n", True)
- self.multitorrent.set_option('max_upload_rate', int(rateNew), None, False)
- return False
- # d
- elif opCode == 'd':
- if len(command) < 2:
- transferLog("invalid rate.\n", True)
- return False
- rateNew = command[1:]
- transferLog("command: setting download-rate to " + rateNew + "...\n", True)
- self.multitorrent.set_option('max_download_rate', int(rateNew), None, False)
- return False
- # r
- elif opCode == 'r':
- if len(command) < 2:
- transferLog("invalid runtime-code.\n", True)
- return False
- runtimeNew = command[1]
- rt = ''
- if runtimeNew == '0':
- rt = 'False'
- elif runtimeNew == '1':
- rt = 'True'
- else:
- transferLog("runtime-code unknown: " + runtimeNew + "\n", True)
- return False
- transferLog("command: setting die-when-done to " + rt + "...\n", True)
- self.d.dieWhenDone = rt
- return False
- # s
- elif opCode == 's':
- if len(command) < 2:
- transferLog("invalid sharekill.\n", True)
- return False
- sharekillNew = command[1:]
- transferLog("command: setting sharekill to " + sharekillNew + "...\n", True)
- self.d.seedLimit = sharekillNew
- return False
- # default
- else:
- transferLog("op-code unknown: " + opCode + "\n", True)
- return False
- #------------------------------------------------------------------------------#
- # __main__ #
- #------------------------------------------------------------------------------#
- if __name__ == '__main__':
- uiname = 'bittorrent-console'
- # args
- defaults = get_defaults(uiname)
- metainfo = None
- if len(sys.argv) <= 1:
- printHelp(uiname, defaults)
- sys.exit(1)
- try:
- # Modifying default values from get_defaults is annoying...
- # Implementing specific default values for each uiname in
- # defaultargs.py is even more annoying. --Dave
- data_dir = [[name, value,doc] for (name, value, doc) in defaults
- if name == "data_dir"][0]
- defaults = [(name, value,doc) for (name, value, doc) in defaults
- if not name == "data_dir"]
- ddir = os.path.join( get_dot_dir(), "console" )
- data_dir[1] = decode_from_filesystem(ddir)
- defaults.append( tuple(data_dir) )
- config, args = configfile.parse_configuration_and_args(defaults,
- uiname, sys.argv[1:], 0, 1)
- torrentfile = None
- if len(args):
- torrentfile = args[0]
- if torrentfile is not None:
- try:
- metainfo = GetTorrent.get(torrentfile)
- except GetTorrent.GetTorrentException, e:
- raise UserFailure(_("Error reading .torrent file: ") + '\n' + unicode(e.args[0]))
- else:
- raise UserFailure(_("you must specify a .torrent file"))
- except BTFailure, e:
- print unicode(e.args[0])
- sys.exit(1)
- except KeyboardInterrupt:
- sys.exit(1)
- # get/set cmd-file
- transferCommandFile = torrentfile + ".cmd"
- # get/set stats-file
- transferStatFile = torrentfile + ".stat"
- # get/set log-file
- transferLogFile = torrentfile + ".log"
- # get/set pid-file
- transferPidFile = torrentfile + ".pid"
- # log what we are starting up
- transferLog("mainline starting up :\n", True)
- transferLog(" - torrentfile : " + torrentfile + "\n", True)
- transferLog(" - save_in : " + config['save_in'] + "\n", True)
- transferLog(" - tf_owner : " + config['tf_owner'] + "\n", True)
- transferLog(" - transferStatFile : " + transferStatFile + "\n", True)
- transferLog(" - transferCommandFile : " + transferCommandFile + "\n", True)
- transferLog(" - transferLogFile : " + transferLogFile + "\n", True)
- transferLog(" - transferPidFile : " + transferPidFile + "\n", True)
- transferLog(" - die_when_done : " + str(config['die_when_done']) + "\n", True)
- transferLog(" - seed_limit : " + str(config['seed_limit']) + "\n", True)
- transferLog(" - minport : " + str(config['minport']) + "\n", True)
- transferLog(" - maxport : " + str(config['maxport']) + "\n", True)
- transferLog(" - max_upload_rate : " + str(config['max_upload_rate']) + "\n", True)
- transferLog(" - max_download_rate : " + str(config['max_download_rate']) + "\n", True)
- transferLog(" - min_uploads : " + str(config['min_uploads']) + "\n", True)
- transferLog(" - max_uploads : " + str(config['max_uploads']) + "\n", True)
- transferLog(" - min_peers : " + str(config['min_peers']) + "\n", True)
- transferLog(" - max_initiate : " + str(config['max_initiate']) + "\n", True)
- transferLog(" - max_incomplete : " + str(config['max_incomplete']) + "\n", True)
- transferLog(" - max_allow_in : " + str(config['max_allow_in']) + "\n", True)
- transferLog(" - rerequest_interval : " + str(config['rerequest_interval']) + "\n", True)
- transferLog(" - start_trackerless_client : " + str(config['start_trackerless_client']) + "\n", True)
- transferLog(" - check_hashes : " + str(config['check_hashes']) + "\n", True)
- transferLog(" - max_files_open : " + str(config['max_files_open']) + "\n", True)
- transferLog(" - upnp : " + str(config['upnp']) + "\n", True)
- # remove command-file if exists
- if isfile(transferCommandFile):
- try:
- transferLog("removing command-file " + transferCommandFile + "...\n", True)
- remove(transferCommandFile)
- except:
- pass
- # app
- app = TorrentApp(metainfo, config)
- try:
- app.run()
- except KeyboardInterrupt:
- pass
- except BTFailure, e:
- print unicode(e.args[0])
- except Exception, e:
- logging.getLogger().exception(e)
- # if after a reasonable amount of time there are still
- # non-daemon threads hanging around then print them.
- nondaemons = [d for d in threading.enumerate() if not d.isDaemon()]
- if len(nondaemons) > 1:
- sleep(4)
- nondaemons = [d for d in threading.enumerate() if not d.isDaemon()]
- if len(nondaemons) > 1:
- print "non-daemon threads not shutting down:"
- for th in nondaemons:
- print " ", th
- # remove pid-file
- transferLog("removing pid-file : " + transferPidFile + "\n", True)
- try:
- remove(transferPidFile)
- except Exception, e:
- transferLog("Failed to remove pid-file : " + transferPidFile + "\n", True)
- # log exit
- transferLog("mainline exit.\n", True)
|