/[gentoo-src]/bittorrent/bt_daemon.py
Gentoo

Contents of /bittorrent/bt_daemon.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download) (as text)
Fri Apr 30 01:13:57 2004 UTC (10 years, 7 months ago) by carpaski
Branch: MAIN
File MIME type: text/x-python
First copy of the bt daemon... Read the code. I'm
lazy and busy at the moment, so I'm really not up
for documentation. -- NJ

1 carpaski 1.1 #!/usr/bin/python -O
2    
3     # Greatly modified by carpaski@gentoo.org
4     # btdownloadheadless written by Bram Cohen
5     # see LICENSE.txt for license information
6    
7    
8     # This is 2^x ... put the x below -- Chunk size for sha1 -- 18 == 256k
9     piece_size_pow2 = 18
10     delay = 0
11     debug = 0
12    
13     # No trailing /
14     file_base = "/usr/portage/distfiles"
15     torrent_base = "/tmp/torrents"
16    
17     COMMENT = "Gentoo Linux BitTorrent Mirror System"
18     tracker = "http://egret.gentoo.org:6969/announce"
19    
20     # Useless variables
21     cols = 80
22     import BitTorrent
23     import os
24     from BitTorrent.download import download
25     from threading import Event,Thread
26     import types
27     import re
28     from os import listdir, getcwd, stat
29     from stat import ST_SIZE
30     from os.path import abspath,isdir,isfile,normpath
31     from sys import argv, stdout, path
32     from cStringIO import StringIO
33     from time import time,ctime,sleep
34    
35     from BitTorrent.makemetafile import make_meta_file
36    
37     def hours(n):
38     if n == -1:
39     return '<unknown>'
40     if n == 0:
41     return 'complete!'
42     n = long(n)
43     h, r = divmod(n, 60 * 60)
44     m, sec = divmod(r, 60)
45     if h > 1000000:
46     return '<unknown>'
47     if h > 0:
48     return '%d hour %02d min %02d sec' % (h, m, sec)
49     else:
50     return '%d min %02d sec' % (m, sec)
51    
52     class HeadlessDisplayer:
53     def __init__(self):
54     self.done = False
55     self.file = ''
56     self.percentDone = ''
57     self.timeEst = ''
58     self.downloadTo = ''
59     self.downRate = ''
60     self.upRate = ''
61     self.downTotal = ''
62     self.upTotal = ''
63     self.errors = []
64     self.last_update_time = 0
65    
66     def finished(self):
67     self.done = True
68     self.percentDone = '100'
69     self.timeEst = 'Download Succeeded!'
70     self.downRate = ''
71     self.display({})
72    
73     def failed(self):
74     self.done = True
75     self.percentDone = '0'
76     self.timeEst = 'Download Failed!'
77     self.downRate = ''
78     self.display({})
79    
80     def error(self, errormsg):
81     self.errors.append(errormsg)
82     self.display({})
83    
84     def display(self, dict):
85     for x in self.errors:
86     print self.file+": "+str(x)
87     self.errors = []
88     return
89    
90     def chooseFile(self, default, size, saveas, dir):
91     self.file = '%s (%.1f MB)' % (default, float(size) / (1 << 20))
92     if saveas != '':
93     default = saveas
94     self.downloadTo = abspath(default)
95     return default
96    
97     def newpath(self, path):
98     self.downloadTo = path
99    
100     def prefix_array(array,prefix,doblanks=1):
101     """Prepends a given prefix to each element in an Array/List/Tuple.
102     Returns a List."""
103     if type(array) not in [types.ListType, types.TupleType]:
104     raise TypeError, "List or Tuple expected. Got %s" % type(array)
105     newarray=[]
106     for x in array:
107     if x or doblanks:
108     newarray.append(prefix + x)
109     else:
110     newarray.append(x)
111     return newarray
112    
113    
114     def list_files(dirlist):
115     file_list = []
116     for mydir in dirlist:
117     if isdir(mydir):
118     try:
119     file_list += list_files(prefix_array(listdir(mydir),mydir+"/"))
120     except Exception,e:
121     print e
122     elif isfile(mydir):
123     file_list.append(mydir)
124     else:
125     print "Unknown type:",mydir
126     return file_list
127    
128    
129     def progress(amount):
130     # Dummy function for the create-torrent progress meter
131     pass
132    
133    
134    
135    
136     if __name__ == '__main__':
137    
138     threads = {}
139     dirs = [torrent_base[:],file_base[:]]
140     re_file = re.compile("("+torrent_base[:]+"|"+file_base[:]+")(/.+?)(\.torrent)?$")
141    
142     while(True):
143     files = list_files(dirs)
144     files.sort()
145     new_files = []
146     torrents = []
147    
148     for f in files:
149     match = re_file.match(f)
150     if not match:
151     print "Failed to match:",f
152     else:
153     if match.group(1) == torrent_base:
154     if match.group(3): # It's a torrent, yay!
155     if match.group(2) not in torrents and stat(f)[ST_SIZE]>0:
156     torrents.append(match.group(2))
157     while(match.group(2) in new_files):
158     del new_files[new_files.index(match.group(2))]
159     elif torrent_base != file_base and debug:
160     print "Not a torrent file:",f
161     if match.group(1) == file_base:
162     if match.group(3) and torrent_base != file_base and debug:
163     print "Torrent in file directory:",f
164     elif match.group(2) not in torrents:
165     if debug:
166     print "New file:",f
167     new_files.append(match.group(2))
168    
169     for t in threads.keys():
170     # Remove threads that we don't have a bittorrent for.
171     if t not in torrents:
172     print "Stopping torrent [%s]: %s" % (ctime(),t)
173     threads[t][0]._Thread__stop()
174     del threads[t]
175     while(t in torrents):
176     del torrents[torrents.index(t)]
177    
178     elif not threads[t][0].isAlive():
179     print "Thread died [%s]: %s" % (ctime(),t)
180     del threads[t]
181    
182     for t in torrents:
183     # Start threads up.
184     if t not in threads.keys():
185     print "Starting torrent [%s]: %s" % (ctime(),t)
186     h = HeadlessDisplayer()
187     try:
188     if not os.path.isdir(file_base+"/"+os.path.dirname(t)):
189     os.makedirs(file_base+"/"+os.path.dirname(t))
190     t_thread = Thread(target=download,name="BitTorrent::"+t,args=(['--responsefile', torrent_base+"/"+t+".torrent", '--saveas', file_base+"/"+t], h.chooseFile, h.display, h.finished, h.error, Event(), cols))
191     threads[t] = [t_thread,h]
192     t_thread.start()
193     sleep(delay)
194     except Exception, e:
195     print "Failed to start thread: %s" % (t)
196     print "Reason: %s" % (str(e))
197    
198     for f in new_files:
199     # Create the torrents for files that don't have them.
200     try:
201     print "Creating torrent [%s]: %s" % (ctime(),f)
202     if not os.path.isdir(torrent_base+"/"+os.path.dirname(f)):
203     os.makedirs(torrent_base+"/"+os.path.dirname(f))
204     make_meta_file(file_base+"/"+f,tracker,piece_size_pow2,progress=progress,comment=COMMENT,target=torrent_base+"/"+f+".torrent")
205     except Exception, e:
206     print "Failed to create torrent: "+str(e)
207    
208     sleep(1)

  ViewVC Help
Powered by ViewVC 1.1.20