instrumentation: add next-share/
[cs-p2p-next.git] / instrumentation / next-share / BaseLib / Tools / dirtrackerseeder.py
1 # Written by Arno Bakker \r
2 # see LICENSE.txt for license information\r
3 #\r
4 # Razvan Deaconescu, 2008:\r
5 #       * corrected problem when running in background\r
6 #       * added usage and print_version functions\r
7 #       * uses getopt for command line argument parsing\r
8 \r
9 import sys\r
10 import shutil\r
11 import time\r
12 import tempfile\r
13 import random\r
14 import os\r
15 import getopt\r
16 from traceback import print_exc\r
17 \r
18 from BaseLib.__init__ import LIBRARYNAME\r
19 from BaseLib.Core.API import *\r
20 from BaseLib.Core.BitTornado.__init__ import version, report_email\r
21 \r
22 MAXUPLOAD = 1000 # KB/s or None\r
23 \r
24 checkpointedwhenseeding = False\r
25 sesjun = None\r
26 \r
27 def usage():\r
28     print "Usage: python dirseeder.py [options] directory"\r
29     print "Options:"\r
30     print "\t--port <port>"\r
31     print "\t-p <port>\t\tuse <port> to listen for connections"\r
32     print "\t\t\t\t(default is random value)"\r
33     print "\tdirectory (default is current)"\r
34     print "\t--seeder\t\t\tseeder only"\r
35     print "\t--version"\r
36     print "\t-v\t\t\tprint version and exit"\r
37     print "\t--help"\r
38     print "\t-h\t\t\tprint this help screen"\r
39     print\r
40     print "Report bugs to <" + report_email + ">"\r
41 \r
42 def print_version():\r
43     print version, "<" + report_email + ">"\r
44 \r
45 def states_callback(dslist):\r
46     allseeding = True\r
47     for ds in dslist:\r
48         state_callback(ds)\r
49         if ds.get_status() != DLSTATUS_SEEDING:\r
50             allseeding = False\r
51         \r
52     global checkpointedwhenseeding\r
53     global sesjun\r
54     if len(dslist) > 0 and allseeding and not checkpointedwhenseeding:\r
55         checkpointedwhenseeding = True\r
56         print >>sys.stderr,"All seeding, checkpointing Session to enable quick restart"\r
57         sesjun.checkpoint()\r
58         \r
59     return (1.0, False)\r
60 \r
61 def state_callback(ds):\r
62     d = ds.get_download()\r
63 #    print >>sys.stderr,`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)\r
64     print >>sys.stderr, '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s' % \\r
65             (`d.get_def().get_name()`, \\r
66             dlstatus_strings[ds.get_status()], \\r
67             ds.get_progress() * 100, \\r
68             ds.get_error(), \\r
69             ds.get_current_speed(UPLOAD), \\r
70             ds.get_current_speed(DOWNLOAD))\r
71 \r
72     return (1.0, False)\r
73 \r
74 def main():\r
75     try:\r
76         opts, args = getopt.getopt(sys.argv[1:], "hvp:", ["help", "version", "port", "seeder"])\r
77     except getopt.GetoptError, err:\r
78         print str(err)\r
79         usage()\r
80         sys.exit(2)\r
81 \r
82     # init to default values\r
83     port = 6969\r
84     tracking  = True\r
85     for o, a in opts:\r
86         if o in ("-h", "--help"):\r
87             usage()\r
88             sys.exit(0)\r
89         elif o in ("-p", "--port"):\r
90             port = int(a)\r
91         elif o in ("-p", "--port"):\r
92             port = int(a)\r
93         elif o in ("--seeder"):\r
94             tracking = False\r
95         elif o in ("-v", "--version"):\r
96             print_version()\r
97             sys.exit(0)\r
98         else:\r
99             assert False, "unhandled option"\r
100 \r
101 \r
102     if len(args) > 1:\r
103         print "Too many arguments"\r
104         usage()\r
105         sys.exit(2)\r
106     elif len(args) == 0:\r
107         torrentsdir = os.getcwd()\r
108     else:\r
109         torrentsdir = os.path.abspath(args[0])\r
110 \r
111     print "Press Ctrl-C or send SIGKILL or WM_DESTROY to stop seeding"\r
112 \r
113     # setup session\r
114     sscfg = SessionStartupConfig()\r
115     statedir = os.path.join(torrentsdir,"."+LIBRARYNAME)\r
116     sscfg.set_state_dir(statedir)\r
117     sscfg.set_listen_port(port)\r
118     sscfg.set_megacache(False)\r
119     sscfg.set_overlay(False)\r
120     sscfg.set_dialback(False)\r
121     if tracking:\r
122         sscfg.set_internal_tracker(True)\r
123         # log full\r
124         logfilename = "tracker-"+str(int(time.time()))+".log"\r
125         sscfg.set_tracker_logfile(logfilename)\r
126         sscfg.set_tracker_log_nat_checks(True)\r
127     \r
128     s = Session(sscfg)\r
129     global sesjun\r
130     sesjun = s\r
131     s.set_download_states_callback(states_callback, getpeerlist=False)\r
132     \r
133     # Restore previous Session\r
134     s.load_checkpoint()\r
135 \r
136     # setup and start downloads\r
137     dscfg = DownloadStartupConfig()\r
138     dscfg.set_dest_dir(torrentsdir)\r
139     # Arno, 2010-04-16: STBSPEED: complete BITFIELDS are processed much faster\r
140     dscfg.set_breakup_seed_bitfield(False)\r
141     if MAXUPLOAD is not None:\r
142         dscfg.set_max_speed(UPLOAD,MAXUPLOAD)\r
143     \r
144     ##dscfg.set_max_uploads(32)\r
145     \r
146     #\r
147     # Scan dir, until exit by CTRL-C (or any other signal/interrupt)\r
148     #\r
149     try:\r
150         while True:\r
151             try:\r
152                 print >>sys.stderr,"Rescanning",`torrentsdir`\r
153                 for torrent_file in os.listdir(torrentsdir):\r
154                     if torrent_file.endswith(".torrent") or torrent_file.endswith(".tstream") or torrent_file.endswith(".url"): \r
155                         print >>sys.stderr,"Found file",`torrent_file`\r
156                         tfullfilename = os.path.join(torrentsdir,torrent_file)\r
157                         if torrent_file.endswith(".url"):\r
158                             f = open(tfullfilename,"rb")\r
159                             url = f.read()\r
160                             f.close()\r
161                             tdef = TorrentDef.load_from_url(url)\r
162                         else:\r
163                             tdef = TorrentDef.load(tfullfilename)\r
164                         \r
165                         # See if already running:\r
166                         dlist = s.get_downloads()\r
167                         existing = False\r
168                         for d in dlist:\r
169                             existinfohash = d.get_def().get_infohash()\r
170                             if existinfohash == tdef.get_infohash():\r
171                                 existing = True\r
172                                 break\r
173                         if existing:\r
174                             print >>sys.stderr,"Ignoring existing Download",`tdef.get_name()`\r
175                             \r
176                             if MAXUPLOAD is not None:\r
177                                 d.set_max_speed(UPLOAD,MAXUPLOAD)\r
178                         else:\r
179                             if tracking:\r
180                                 s.add_to_internal_tracker(tdef)\r
181                             d = s.start_download(tdef, dscfg)\r
182                             \r
183                             # Checkpoint again when new are seeding\r
184                             global checkpointedwhenseeding\r
185                             checkpointedwhenseeding = False\r
186                             \r
187             except KeyboardInterrupt,e:\r
188                 raise e\r
189             except Exception, e:\r
190                 print_exc()\r
191             \r
192             time.sleep(30.0)\r
193 \r
194     except Exception, e:\r
195         print_exc()\r
196 \r
197 if __name__ == "__main__":\r
198     main()\r