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

Diff of /bittorrent/bt_daemon.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.4 Revision 1.5
1#!/usr/bin/python -O 1#!/usr/bin/python -O
2# $Id: bt_daemon.py,v 1.4 2004/05/25 23:51:44 carpaski Exp $ 2# $Id: bt_daemon.py,v 1.5 2004/06/16 05:15:31 carpaski Exp $
3# 3#
4# Greatly modified by carpaski@gentoo.org 4# Greatly modified by carpaski@gentoo.org
5# btdownloadheadless written by Bram Cohen 5# btdownloadheadless written by Bram Cohen
6# see LICENSE.txt for license information 6# see LICENSE.txt for license information
7 7
8import os,sys 8import os,sys,string
9os.nice(5) 9os.nice(5)
10 10
11sys.path = ["/usr/lib/portage/pym"] + sys.path + ["/usr/bin"] 11sys.path = ["/usr/lib/portage/pym"] + sys.path + ["/usr/bin"]
12from portage import getconfig 12from portage import getconfig
13 13
14import BitTorrent 14import BitTorrent
15from BitTorrent.download import download 15from BitTorrent.download import download
16
16from threading import Event,Thread 17from threading import Event,Thread
17import types 18import types,traceback,re,random
18import re 19
19from os import listdir, getcwd, stat 20from os import listdir, getcwd, stat
20from stat import ST_SIZE,ST_MTIME 21from stat import ST_SIZE,ST_MTIME
21from os.path import abspath,isdir,isfile,normpath 22from os.path import abspath,isdir,isfile,normpath
22from sys import argv, stdout, path 23from sys import argv, stdout, path
23from cStringIO import StringIO 24from cStringIO import StringIO
40 else: 41 else:
41 return '%d min %02d sec' % (m, sec) 42 return '%d min %02d sec' % (m, sec)
42 43
43class HeadlessDisplayer: 44class HeadlessDisplayer:
44 def __init__(self): 45 def __init__(self):
46 self.active = False
45 self.done = False 47 self.done = False
46 self.failed = False 48 self.failed = False
47 self.file = '' 49 self.file = ''
48 self.activity = '' 50 self.activity = ''
49 self.percentDone = 0.0 51 self.percentDone = 0.0
87 self.timeEst = long(dict['timeEst']) 89 self.timeEst = long(dict['timeEst'])
88 if dict.has_key('activity') and not self.done: 90 if dict.has_key('activity') and not self.done:
89 self.activity = dict['activity'] 91 self.activity = dict['activity']
90 if dict.has_key('downRate'): 92 if dict.has_key('downRate'):
91 self.downRate = float(dict['downRate']) / (1 << 10) 93 self.downRate = float(dict['downRate']) / (1 << 10)
94 if self.downRate > 0:
95 self.has_transfered = True
92 if dict.has_key('upRate'): 96 if dict.has_key('upRate'):
93 self.upRate = float(dict['upRate']) / (1 << 10) 97 self.upRate = float(dict['upRate']) / (1 << 10)
98 if self.upRate > 0:
99 self.has_transfered = True
94 if dict.has_key('upTotal'): 100 if dict.has_key('upTotal'):
95 self.upTotal = dict['upTotal'] 101 self.upTotal = dict['upTotal']
96 if dict.has_key('downTotal'): 102 if dict.has_key('downTotal'):
103 self.active = True
97 self.downTotal = dict['downTotal'] 104 self.downTotal = dict['downTotal']
98 for x in self.errors: 105 for x in self.errors:
99 print self.file+": "+str(x) 106 print self.file+": "+str(x)
100 self.errors = [] 107 self.errors = []
101 return 108 return
141def progress(amount): 148def progress(amount):
142 # Dummy function for the create-torrent progress meter 149 # Dummy function for the create-torrent progress meter
143 pass 150 pass
144 151
145 152
146def writemsg(msg,fileName,overwrite=0, create=0): 153def writemsg(msg,fileName,overwrite=0,create=0,echo=1):
147 if overwrite or create: 154 if overwrite or create:
148 fileHandle = open(fileName, "w") 155 fileHandle = open(fileName, "w")
149 else: 156 else:
150 fileHandle = open(fileName, "a") 157 fileHandle = open(fileName, "a")
151 158
152 fileHandle.write(msg+"\n") 159 fileHandle.write(msg+"\n")
153 fileHandle.flush() 160 fileHandle.flush()
154 fileHandle.close() 161 fileHandle.close()
162 if echo:
155 print msg 163 print msg
156 164
157 165
158# Useless variables 166# Useless variables
159cols = 80 167cols = 80
160 168
161# This is 2^x ... put the x below -- Chunk size for sha1 -- 18 == 256k 169# This is 2^x ... put the x below -- Chunk size for sha1 -- 18 == 256k
162piece_size_pow2 = 18 170piece_size_pow2 = 18
163max_starting_threads = 10 171max_starting_threads = 1
164loop_mod = 4320 # Rotating value (for logs) 172loop_mod = 4320 # Rotating value (for logs)
165rotate_logs = 0 # Make one log or roate into loop_mod logs 173rotate_logs = 0 # Make one log or roate into loop_mod logs
166cycle_sleep = 20 174cycle_sleep = 20
167spawn_thread_delay = 0 175spawn_thread_delay = 0
168debug = 0 176debug = 0
169minimum_age = 30 177minimum_age = 30
170port_min = 6881 178port_min = 6881
171port_max = 7280 179port_max = 7280
172check_hashes = 0 180check_hashes = 0
181shuffle_files = 1
182master_seed = 0
183min_uploads = 20
184max_uploads = 20
185download_slice_size = 65536
186max_slice_length = 131072
187request_backlog = 20
188timeout = 90
189timeout_check_interval = 20
190stats = 1
173 191
174# No trailing / 192# No trailing /
175file_base = "/usr/portage/distfiles" 193file_base = "/usr/portage/distfiles"
176torrent_base = "/tmp/torrents" 194torrent_base = "/tmp/torrents"
177 195
178comment = "Gentoo Linux BitTorrent Mirror System" 196comment = "Gentoo Linux BitTorrent Mirror System"
179tracker = "http://egret.gentoo.org:6969/announce" 197tracker = "http://egret.gentoo.org:6969/announce"
180 198
181if __name__ == '__main__': 199if __name__ == '__main__':
182 mydict = getconfig("bt_daemon.conf") 200 try:
183 if not mydict:
184 print "bt_daemon.conf is missing"
185 sys.exit(1)
186
187 if mydict.has_key("file_base") and mydict["file_base"]:
188 file_base = os.path.normpath(mydict["file_base"])
189 else:
190 print "file_base not specified in config."
191 sys.exit(1)
192
193 if mydict.has_key("torrent_base") and mydict["torrent_base"]:
194 torrent_base = os.path.normpath(mydict["torrent_base"])
195 else:
196 print "torrent_base not specified in config."
197 sys.exit(1)
198
199 threads = {}
200 dirs = [torrent_base[:],file_base[:]]
201 re_file = re.compile("("+torrent_base[:]+"|"+file_base[:]+")(/.+?)(\.torrent)?$")
202 absmax_upRate = 0.0
203 absmax_upFile = ''
204
205 loop_val = 0
206 while(True):
207 mydict = getconfig("bt_daemon.conf") 201 mydict = getconfig("bt_daemon.conf")
208 if not mydict: 202 if not mydict:
209 print "bt_daemon.conf is missing" 203 print "bt_daemon.conf is missing"
204
205 if mydict.has_key("file_base") and mydict["file_base"]:
206 file_base = os.path.normpath(mydict["file_base"])
207 else:
208 print "file_base not specified in config."
210 sys.exit(1) 209 sys.exit(1)
211 210
212 if mydict.has_key("piece_size_pow2"):
213 piece_size_pow2 = int(mydict["piece_size_pow2"])
214 if mydict.has_key("max_starting_threads"):
215 max_starting_threads = int(mydict["max_starting_threads"])
216 if mydict.has_key("loop_mod"):
217 loop_mod = int(mydict["loop_mod"])
218 if mydict.has_key("rotate_logs"):
219 rotate_logs = int(mydict["rotate_logs"])
220 if mydict.has_key("cycle_sleep"):
221 cycle_sleep = int(mydict["cycle_sleep"])
222 if mydict.has_key("spawn_thread_delay"):
223 spawn_thread_delay = int(mydict["spawn_thread_delay"])
224 if mydict.has_key("debug"):
225 debug = int(mydict["debug"])
226
227 if mydict.has_key("comment"):
228 comment = mydict["comment"]
229 if mydict.has_key("port_min"):
230 port_min = mydict["port_min"]
231 if mydict.has_key("port_max"):
232 port_max = mydict["port_max"]
233 if mydict.has_key("check_hashes"):
234 check_hashes = mydict["check_hashes"]
235
236 if mydict.has_key("tracker") and mydict["tracker"]: 211 if mydict.has_key("torrent_base") and mydict["torrent_base"]:
237 tracker = mydict["tracker"] 212 torrent_base = os.path.normpath(mydict["torrent_base"])
238 else: 213 else:
239 print "tracker not specified in config." 214 print "torrent_base not specified in config."
240 sys.exit(1) 215 sys.exit(1)
241 216
242 217 threads = {}
243 loop_val = (loop_val + 1) % loop_mod 218 dirs = [torrent_base[:],file_base[:]]
244 files = list_files(dirs) 219 re_file = re.compile("("+torrent_base[:]+"|"+file_base[:]+")(/.+?)(\.torrent)?$")
245 files.sort() 220 absmax_upRate = 0.0
246 new_files = [] 221 absmax_upFile = ''
247 torrents = [] 222
248 223 loop_val = 0
249 for f in files: 224 while(True):
250 match = re_file.match(f) 225 mydict = getconfig("bt_daemon.conf")
251 if not match: 226 if not mydict:
252 print "Failed to match:",f 227 sys.stderr.write("bt_daemon.conf is missing or contains errors\n")
228
229 if mydict.has_key("master_seed"):
230 master_seed = int(mydict["master_seed"])
231
232 if mydict.has_key("piece_size_pow2"):
233 piece_size_pow2 = int(mydict["piece_size_pow2"])
234 if mydict.has_key("max_starting_threads"):
235 max_starting_threads = int(mydict["max_starting_threads"])
236 if mydict.has_key("loop_mod"):
237 loop_mod = int(mydict["loop_mod"])
238 if mydict.has_key("rotate_logs"):
239 rotate_logs = int(mydict["rotate_logs"])
240 if mydict.has_key("cycle_sleep"):
241 cycle_sleep = int(mydict["cycle_sleep"])
242 if mydict.has_key("spawn_thread_delay"):
243 spawn_thread_delay = int(mydict["spawn_thread_delay"])
244 if mydict.has_key("debug"):
245 debug = int(mydict["debug"])
246
247 if mydict.has_key("min_uploads"):
248 min_uploads = int(mydict["min_uploads"])
249 if mydict.has_key("max_uploads"):
250 max_uploads = int(mydict["max_uploads"])
251 if mydict.has_key("download_slice_size"):
252 download_slice_size = int(mydict["download_slice_size"])
253 if mydict.has_key("max_slice_length"):
254 max_slice_length = int(mydict["max_slice_length"])
255 if mydict.has_key("request_backlog"):
256 request_backlog = int(mydict["request_backlog"])
257 if mydict.has_key("timeout"):
258 timeout = int(mydict["timeout"])
259 if mydict.has_key("timeout_check_interval"):
260 timeout_check_interval = int(mydict["timeout_check_interval"])
261
262 if mydict.has_key("comment"):
263 comment = mydict["comment"]
264 if mydict.has_key("port_min"):
265 port_min = mydict["port_min"]
266 if mydict.has_key("port_max"):
267 port_max = mydict["port_max"]
268 if mydict.has_key("check_hashes"):
269 check_hashes = mydict["check_hashes"]
270
271 if mydict.has_key("tracker") and mydict["tracker"]:
272 tracker = mydict["tracker"]
253 else: 273 else:
274 print "tracker not specified in config."
275 sys.exit(1)
276
277
278 loop_val = (loop_val + 1) % loop_mod
279 files = list_files(dirs)
280 files.sort()
281 new_files = []
282 torrents = []
283
284 if shuffle_files:
285 random.shuffle(files)
286
287 for f in files:
288 try:
289 match = re_file.match(f)
290 if not match:
291 print "Failed to match:",f
292 else:
254 if match.group(1) == torrent_base: 293 if match.group(1) == torrent_base:
255 if match.group(3): # It's a torrent, yay! 294 if match.group(3): # It's a torrent, yay!
256 if match.group(2) not in torrents: 295 if match.group(2) not in torrents:
257 mystat = stat(f) 296 mystat = stat(f)
258 # only add if it has a size and is not actively modified. 297 # only add if it has a size and is not actively modified.
298 if mystat[ST_SIZE]>0 and (time()-mystat[ST_MTIME])>minimum_age:
299 torrents.append(match.group(2))
300 while(match.group(2) in new_files):
301 del new_files[new_files.index(match.group(2))]
302 elif torrent_base != file_base and debug:
303 print "Not a torrent file:",f
304 if match.group(1) == file_base:
305 if match.group(3) and torrent_base != file_base and debug:
306 print "Torrent in file directory:",f
307 elif match.group(2) not in torrents:
308 mystat = stat(f)
259 if mystat[ST_SIZE]>0 and (time()-mystat[ST_MTIME])>minimum_age: 309 if mystat[ST_SIZE]>0 and (time()-mystat[ST_MTIME])>minimum_age:
260 torrents.append(match.group(2))
261 while(match.group(2) in new_files):
262 del new_files[new_files.index(match.group(2))]
263 elif torrent_base != file_base and debug:
264 print "Not a torrent file:",f
265 if match.group(1) == file_base:
266 if match.group(3) and torrent_base != file_base and debug:
267 print "Torrent in file directory:",f
268 elif match.group(2) not in torrents:
269 if debug:
270 print "New file:",f
271 mystat = stat(f)
272 if mystat[ST_SIZE]>0 and (time()-mystat[ST_MTIME])>minimum_age:
273 new_files.append(match.group(2)) 310 new_files.append(match.group(2))
274 311 if debug:
312 print "New file:",f
313 else:
314 if debug:
315 print "Actively modified: ",f
316 except Exception,e:
317 traceback.print_last()
318 print "--- IGNORING FILE:",t
319 print
320
275 for t in threads.keys(): 321 for t in threads.keys():
276 # Remove threads that we don't have a bittorrent for. 322 # Remove threads that we don't have a bittorrent for.
277 if t not in torrents or not os.path.exists(file_base+t): 323 if t not in torrents or not os.path.exists(file_base+t):
278 print "Stopping torrent [%s]: %s" % (ctime(),t) 324 print "Stopping torrent [%s]: %s" % (ctime(),t)
279 threads[t][0]._Thread__stop() 325 threads[t][0]._Thread__stop()
280 del threads[t] 326 del threads[t]
281 while(t in torrents): 327 while(t in torrents):
282 del torrents[torrents.index(t)] 328 del torrents[torrents.index(t)]
329
330 elif not threads[t][0].isAlive():
331 print "Thread died [%s]: %s" % (ctime(),t)
332 del threads[t]
333
334 completed = []
335 fetching = []
336 hashing = []
337 stalled = []
338
339 stats_up = []
340 stats_down = []
341
342 totalup = 0
343 rateup = 0
344 ratedown = 0
345
346 max_up_rate = 0
347 max_up_file = ''
348 max_down_rate = 0
349 max_down_file = ''
350 completed_string = ""
351 for t in threads.keys():
352 # Let's do some stats.
353 if not threads[t][1].failed and threads[t][0].isAlive():
354 if threads[t][1].done:
355 completed.append(t)
356 else:
357 fetching.append(t)
358 if not threads[t][1].active:
359 hashing.append(t)
360 elif threads[t][1].downRate == 0:
361 stalled.append(t)
362
363 stats_up.append("%s\tT:%f\tR:%03.2f\t%s" % (t,threads[t][1].upTotal,threads[t][1].upRate,threads[t][1].activity))
364 stats_down.append("%s\tT:%f\tR:%03.2f\t%s" % (t,threads[t][1].percentDone,threads[t][1].downRate,threads[t][1].activity))
365
366 totalup += threads[t][1].upTotal
367
368 rateup += threads[t][1].upRate
369 if threads[t][1].upRate > max_up_rate:
370 max_up_rate = threads[t][1].upRate
371 max_up_file = threads[t][1].file[:]
372 if threads[t][1].upRate > absmax_upRate:
373 absmax_upRate = threads[t][1].upRate
374 absmax_upFile = threads[t][1].file[:]
375
376 ratedown += threads[t][1].downRate
377 if threads[t][1].downRate > max_down_rate:
378 max_down_rate = threads[t][1].downRate
379 max_down_file = threads[t][1].file[:]
380
381 if stats:
382 if rotate_logs:
383 filename = "bt_daemon-%d-%04d.stats" % (os.getpid(),loop_val)
384 makenew = 1
385 else:
386 filename = "bt_daemon-%d.stats" % (os.getpid())
387 makenew = 0
388 writemsg("",filename,overwrite=makenew)
389 writemsg("Stats: %s" % (ctime()) ,filename)
390 writemsg("Seeding: %d" % (len(completed)) ,filename)
391 writemsg("Fetching: %d (stalled: %d) (hashing: %d)" % (len(fetching),len(stalled),len(hashing)),filename)
392 writemsg("Total up: %.3f MB" % (totalup) ,filename)
393 writemsg("UpRate: %.2f k/s" % (rateup) ,filename)
394 writemsg("UpMaxNow: %.2f k/s '%s'" % (max_up_rate,max_up_file) ,filename)
395 writemsg("UpAbsMax: %.2f k/s '%s'" % (absmax_upRate,absmax_upFile) ,filename)
396 writemsg("DownRate: %.2f k/s" % (ratedown) ,filename)
397 writemsg("DownBest: %.2f k/s '%s'" % (max_down_rate,max_down_file) ,filename)
398 writemsg("",filename)
283 399
284 elif not threads[t][0].isAlive(): 400 completed.sort()
285 print "Thread died [%s]: %s" % (ctime(),t) 401 writemsg(string.join(completed, "\n"), filename+".completed", overwrite=1, echo=0)
286 del threads[t] 402 hashing.sort()
287 403 writemsg(string.join(hashing, "\n"), filename+".hashing", overwrite=1, echo=0)
288 fetching = 0 404 stalled.sort()
289 completed = 0 405 writemsg(string.join(stalled, "\n"), filename+".stalled", overwrite=1, echo=0)
290 stalled = 0 406 stats_up.sort()
291 totalup = 0 407 writemsg(string.join(stats_up, "\n"), filename+".stats_up", overwrite=1, echo=0)
292 rateup = 0 408 stats_down.sort()
293 ratedown = 0 409 writemsg(string.join(stats_down, "\n"), filename+".stats_down", overwrite=1, echo=0)
294 410
295 max_up_rate = 0
296 max_up_file = ''
297 max_down_rate = 0
298 max_down_file = ''
299 for t in threads.keys():
300 # Let's do some stats.
301 if not threads[t][1].failed and threads[t][0].isAlive():
302 if threads[t][1].done:
303 completed += 1
304 else:
305 fetching += 1
306 if threads[t][1].downRate == 0:
307 stalled += 1
308
309 totalup += threads[t][1].upTotal
310
311 rateup += threads[t][1].upRate
312 if threads[t][1].upRate > max_up_rate:
313 max_up_rate = threads[t][1].upRate
314 max_up_file = threads[t][1].file[:]
315 if threads[t][1].upRate > absmax_upRate:
316 absmax_upRate = threads[t][1].upRate
317 absmax_upFile = threads[t][1].file[:]
318
319 ratedown += threads[t][1].downRate
320 if threads[t][1].downRate > max_down_rate:
321 max_down_rate = threads[t][1].downRate
322 max_down_file = threads[t][1].file[:]
323
324 if os.path.exists(".stats"):
325 if ROTATE_LOGS:
326 filename = "bt_daemon-%d-%04d.stats" % (os.getpid(),loop_val)
327 makenew = 1
328 else:
329 filename = "bt_daemon-%d.stats" % (os.getpid())
330 makenew = 0
331 writemsg("",filename,overwrite=makenew)
332 writemsg("Stats: %s" % (ctime()) ,filename)
333 writemsg("Seeding: %d" % (completed) ,filename)
334 writemsg("Fetching: %d(%d)" % (fetching,stalled) ,filename)
335 writemsg("Total up: %.3f MB" % (totalup) ,filename)
336 writemsg("UpRate: %.2f k/s" % (rateup) ,filename)
337 writemsg("UpMaxNow: %.2f k/s '%s'" % (max_up_rate,max_up_file) ,filename)
338 writemsg("UpAbsMax: %.2f k/s '%s'" % (absmax_upRate,absmax_upFile) ,filename)
339 writemsg("DownRate: %.2f k/s" % (ratedown) ,filename)
340 writemsg("DownBest: %.2f k/s '%s'" % (max_down_rate,max_down_file) ,filename)
341 writemsg("",filename)
342
343 for t in torrents: 411 for t in torrents:
344 # Start threads up if we have load free for them. Startup is harsh. 412 # Start threads up if we have load free for them. Startup is harsh.
345 if t not in threads.keys() and ((len(threads.keys())-completed) < max_starting_threads): 413 if t not in threads.keys() and (max_starting_threads - len(hashing) > 0):
414 hashing.append(t)
346 print "Starting torrent [%s]: %s" % (ctime(),t) 415 print "Starting torrent [%s]: %s" % (ctime(),t)
347 h = HeadlessDisplayer() 416 h = HeadlessDisplayer()
348 try: 417 try:
349 if not os.path.isdir(file_base+"/"+os.path.dirname(t)): 418 if not os.path.isdir(file_base+"/"+os.path.dirname(t)):
350 os.makedirs(file_base+"/"+os.path.dirname(t)) 419 os.makedirs(file_base+"/"+os.path.dirname(t))
351 download_args = [ 420 download_args = [
352 # responsefile -> Torrent filename 421 # responsefile -> Torrent filename
353 '--responsefile', torrent_base+"/"+t+".torrent", 422 '--responsefile', torrent_base+"/"+t+".torrent",
354 # saveas -> Real filename 423 # saveas -> Real filename
355 '--saveas', file_base+"/"+t, 424 '--saveas', file_base+"/"+t,
356 # max_slice_length -> How much we can get in a single request 425 # max_slice_length -> How much we can send in a single request
357 '--max_slice_length', "65536", 426 '--max_slice_length', str(max_slice_length),
358 # timeout_check_interval -> Time between timeout checks 427 # timeout_check_interval -> Time between timeout checks
359 '--timeout_check_interval', '30', 428 '--timeout_check_interval', str(timeout_check_interval),
360 # timeout -> How long until we time out a connection 429 # timeout -> How long until we time out a connection
361 '--timeout', '120', 430 '--timeout', str(timeout),
362 # minport -> Lowest port allowed for files 431 # minport -> Lowest port allowed for files
363 '--minport', str(port_min), 432 '--minport', str(port_min),
364 # maxport -> Highest port allowed for files 433 # maxport -> Highest port allowed for files
365 '--maxport', str(port_max), 434 '--maxport', str(port_max),
366 # request_backlog -> How many requests per pipe do we hold 435 # request_backlog -> How many requests per pipe do we hold
367 '--request_backlog', '20', 436 '--request_backlog', str(request_backlog),
368 # download_slice_size -> How much do we request? 437 # download_slice_size -> How much do we request?
369 '--download_slice_size', '65536', 438 '--download_slice_size', str(download_slice_size),
370 # max_uploads -> How many do we serve out? 439 # max_uploads -> How many do we serve out?
371 '--max_uploads', '20', 440 '--max_uploads', str(max_uploads),
441 # min_uploads -> When do we switch from random to rare?
442 '--min_uploads', str(min_uploads),
372 # check_hashes -> Do we check the on-disk files before joining? 443 # check_hashes -> Do we check the on-disk files before joining?
373 '--check_hashes', str(check_hashes) 444 '--check_hashes', str(check_hashes)
374 ] 445 ]
375 t_thread = Thread(target=download,name="BitTorrent::"+t,args=(download_args, h.chooseFile, h.display, h.finished, h.error, Event(), cols)) 446 t_thread = Thread(target=download,name="BitTorrent::"+t,args=(download_args, h.chooseFile, h.display, h.finished, h.error, Event(), cols))
376 threads[t] = [t_thread,h] 447 threads[t] = [t_thread,h]
377 t_thread.start() 448 t_thread.start()
378 sleep(spawn_thread_delay) 449 sleep(spawn_thread_delay)
379 except Exception, e: 450 except Exception, e:
380 print "Failed to start thread: %s" % (t) 451 print "Failed to start thread: %s" % (t)
381 print "Reason: %s" % (str(e)) 452 print "Reason: %s" % (str(e))
382 453
454 if master_seed:
383 for f in new_files: 455 for f in new_files:
384 # Create the torrents for files that don't have them. 456 # Create the torrents for files that don't have them.
385 try: 457 try:
386 print "Creating torrent [%s]: %s" % (ctime(),f) 458 print "Creating torrent [%s]: %s" % (ctime(),f)
387 if not os.path.isdir(torrent_base+"/"+os.path.dirname(f)): 459 if not os.path.isdir(torrent_base+"/"+os.path.dirname(f)):
388 os.makedirs(torrent_base+"/"+os.path.dirname(f)) 460 os.makedirs(torrent_base+"/"+os.path.dirname(f))
389 make_meta_file(file_base+"/"+f,tracker,piece_size_pow2,progress=progress,comment=comment,target=torrent_base+"/"+f+".torrent") 461 make_meta_file(file_base+"/"+f,tracker,piece_size_pow2,progress=progress,comment=comment,target=torrent_base+"/"+f+".torrent")
390 except Exception, e: 462 except Exception, e:
391 print "Failed to create torrent: "+str(e) 463 print "Failed to create torrent: "+str(e)
392 464
393 sleep(cycle_sleep) 465 sleep(cycle_sleep)
466 except Exception, e:
467 import signal,traceback
468 print e
469 traceback.print_stack()
470 os.kill(0,signal.SIGTERM)

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

  ViewVC Help
Powered by ViewVC 1.1.20