murder 0.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +1 -0
  2. data/LICENSE +17 -0
  3. data/README +224 -0
  4. data/Rakefile +52 -0
  5. data/VERSION +1 -0
  6. data/dist/BitTornado/BT1/Choker.py +128 -0
  7. data/dist/BitTornado/BT1/Connecter.py +288 -0
  8. data/dist/BitTornado/BT1/Downloader.py +594 -0
  9. data/dist/BitTornado/BT1/DownloaderFeedback.py +155 -0
  10. data/dist/BitTornado/BT1/Encrypter.py +333 -0
  11. data/dist/BitTornado/BT1/FileSelector.py +245 -0
  12. data/dist/BitTornado/BT1/Filter.py +12 -0
  13. data/dist/BitTornado/BT1/HTTPDownloader.py +251 -0
  14. data/dist/BitTornado/BT1/NatCheck.py +95 -0
  15. data/dist/BitTornado/BT1/PiecePicker.py +320 -0
  16. data/dist/BitTornado/BT1/Rerequester.py +426 -0
  17. data/dist/BitTornado/BT1/Statistics.py +177 -0
  18. data/dist/BitTornado/BT1/Storage.py +584 -0
  19. data/dist/BitTornado/BT1/StorageWrapper.py +1045 -0
  20. data/dist/BitTornado/BT1/StreamCheck.py +135 -0
  21. data/dist/BitTornado/BT1/T2T.py +193 -0
  22. data/dist/BitTornado/BT1/Uploader.py +145 -0
  23. data/dist/BitTornado/BT1/__init__.py +1 -0
  24. data/dist/BitTornado/BT1/btformats.py +100 -0
  25. data/dist/BitTornado/BT1/fakeopen.py +89 -0
  26. data/dist/BitTornado/BT1/makemetafile.py +263 -0
  27. data/dist/BitTornado/BT1/track.py +1067 -0
  28. data/dist/BitTornado/ConfigDir.py +401 -0
  29. data/dist/BitTornado/ConfigReader.py +1068 -0
  30. data/dist/BitTornado/ConnChoice.py +31 -0
  31. data/dist/BitTornado/CreateIcons.py +105 -0
  32. data/dist/BitTornado/CurrentRateMeasure.py +37 -0
  33. data/dist/BitTornado/HTTPHandler.py +167 -0
  34. data/dist/BitTornado/PSYCO.py +5 -0
  35. data/dist/BitTornado/RateLimiter.py +153 -0
  36. data/dist/BitTornado/RateMeasure.py +75 -0
  37. data/dist/BitTornado/RawServer.py +195 -0
  38. data/dist/BitTornado/ServerPortHandler.py +188 -0
  39. data/dist/BitTornado/SocketHandler.py +375 -0
  40. data/dist/BitTornado/__init__.py +63 -0
  41. data/dist/BitTornado/bencode.py +319 -0
  42. data/dist/BitTornado/bitfield.py +162 -0
  43. data/dist/BitTornado/clock.py +27 -0
  44. data/dist/BitTornado/download_bt1.py +882 -0
  45. data/dist/BitTornado/inifile.py +169 -0
  46. data/dist/BitTornado/iprangeparse.py +194 -0
  47. data/dist/BitTornado/launchmanycore.py +381 -0
  48. data/dist/BitTornado/natpunch.py +254 -0
  49. data/dist/BitTornado/parseargs.py +137 -0
  50. data/dist/BitTornado/parsedir.py +150 -0
  51. data/dist/BitTornado/piecebuffer.py +86 -0
  52. data/dist/BitTornado/selectpoll.py +109 -0
  53. data/dist/BitTornado/subnetparse.py +218 -0
  54. data/dist/BitTornado/torrentlistparse.py +38 -0
  55. data/dist/BitTornado/zurllib.py +100 -0
  56. data/dist/murder_client.py +291 -0
  57. data/dist/murder_make_torrent.py +46 -0
  58. data/dist/murder_tracker.py +28 -0
  59. data/doc/examples/Capfile +28 -0
  60. data/lib/capistrano/recipes/deploy/strategy/murder.rb +52 -0
  61. data/lib/murder.rb +43 -0
  62. data/lib/murder/admin.rb +47 -0
  63. data/lib/murder/murder.rb +121 -0
  64. data/murder.gemspec +101 -0
  65. metadata +129 -0
@@ -0,0 +1,28 @@
1
+ # Capfile with example murder config
2
+
3
+ require 'rubygems'
4
+ require 'murder'
5
+
6
+ set :application, 'example-app'
7
+
8
+ set :scm, 'git'
9
+ set :repository, 'ssh://git.example.com/my/app.git'
10
+ set :copy_exclude, '.git'
11
+
12
+ # use murder
13
+ set :deploy_via, :murder
14
+
15
+ # convenient hooks
16
+ after 'deploy:setup', 'murder:distribute_files' # setup remote murder support files on all hosts
17
+ before 'murder:start_seeding', 'murder:start_tracker' # let deploy manage the tracker as well
18
+ after 'murder:stop_seeding', 'murder:stop_tracker'
19
+
20
+ # define an app server role
21
+ role :app, 'w01', 'w02', 'w03', 'w04', 'w05'
22
+
23
+ # murder roles (optional. seeder/tracker will default to the first deployable server)
24
+ role :tracker, 'tracker01'
25
+ role :seeder, 'seeder01'
26
+ # peer role defaults to all deployable servers (all except :no_release => true)
27
+ # you shouldn't need to set this if you are using the deploy strategy.
28
+ #role :peer, 'w01', 'w02', 'w03', 'w04', 'w05'
@@ -0,0 +1,52 @@
1
+ # Copyright 2010 Twitter, Inc.
2
+ # Copyright 2010 Larry Gadea <lg@twitter.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'capistrano/recipes/deploy/strategy/copy'
17
+
18
+ module Capistrano
19
+ module Deploy
20
+ module Strategy
21
+ class Murder < Capistrano::Deploy::Strategy::Copy
22
+ def upload(filename, remote_filename)
23
+ puts "Uploading release to seeder..."
24
+ configuration.upload(filename, remote_filename, :roles => :seeder)
25
+
26
+ ENV["tag"] = File.basename(filename)
27
+ ENV["path_is_file"] = "yes"
28
+ ENV["files_path"] = remote_filename
29
+ ENV['destination_path'] = remote_filename
30
+
31
+ puts "Creating torrent..."
32
+ murder.create_torrent
33
+
34
+ puts "Starting seeding..."
35
+ murder.start_seeding
36
+
37
+ puts "Peering..."
38
+ murder.peer
39
+
40
+ puts "Done. Killing seeding and all peering..."
41
+ murder.stop_peering
42
+ murder.stop_seeding
43
+
44
+ puts "Cleaning temp files..."
45
+ murder.clean_temp_files
46
+
47
+ puts "THANK YOU FOR USING MURDER, HAVE A NICE DAY"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
data/lib/murder.rb ADDED
@@ -0,0 +1,43 @@
1
+ # Copyright 2010 Twitter, Inc.
2
+ # Copyright 2010 Larry Gadea <lg@twitter.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ Capistrano::Configuration.instance(:must_exist).load do
17
+
18
+ load_paths.push File.expand_path('../', __FILE__)
19
+
20
+ load 'murder/murder'
21
+ load 'murder/admin'
22
+
23
+ # no default defaults...
24
+ set :default_tag, ''
25
+ set :default_seeder_files_path, ''
26
+ set :default_destination_path, ''
27
+
28
+ # default remote dist path in app shared directory
29
+ set(:remote_murder_path) { "#{shared_path}/murder" }
30
+
31
+ # roles
32
+ excluded_roles = [:peer, :tracker, :seeder]
33
+
34
+ # get around the fact that find_servers does not work in role evaluation
35
+ # (it tries to evaluate all roles, leading to infinite recursion)
36
+ role :peer do
37
+ roles.reject{|k,v| excluded_roles.include? k }.values.map(&:servers).flatten.uniq.reject{|s| s.options[:no_release] }
38
+ end
39
+
40
+ role(:tracker) { roles[:peer].servers.first }
41
+ role(:seeder) { roles[:peer].servers.first }
42
+
43
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2010 Twitter, Inc.
2
+ # Copyright 2010 Larry Gadea <lg@twitter.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ namespace :murder do
17
+ task :distribute_files, :roles => [:tracker, :seeder, :peer] do
18
+ dist_path = File.expand_path('../../dist', __FILE__)
19
+
20
+ run "mkdir -p #{remote_murder_path}/"
21
+ run "[ $(find '#{remote_murder_path}/'* | wc -l ) -lt 1000 ] && rm -rf '#{remote_murder_path}/'* || ( echo 'Cowardly refusing to remove files! Check the remote_murder_path.' ; exit 1 )"
22
+
23
+ # TODO: Skip hidden (.*) files
24
+ # TODO: Specifyable tmp file
25
+ system "tar -c -z -C #{dist_path} -f /tmp/murder_dist.tgz ."
26
+ upload("/tmp/murder_dist.tgz", "/tmp/murder_dist.tgz", :via => :sftp)
27
+ run "tar xf /tmp/murder_dist.tgz -C #{remote_murder_path}"
28
+ run "rm /tmp/murder_dist.tgz"
29
+ system "rm /tmp/murder_dist.tgz"
30
+ end
31
+
32
+ task :start_tracker, :roles => :tracker do
33
+ run("screen -dms murder_tracker python #{remote_murder_path}/murder_tracker.py && sleep 0.2", :pty => true)
34
+ end
35
+
36
+ task :stop_tracker, :roles => :tracker do
37
+ run("pkill -f 'SCREEN.*murder_tracker.py'")
38
+ end
39
+
40
+ task :stop_all_seeding, :roles => :seeder do
41
+ run("pkill -f \"SCREEN.*seeder-\"")
42
+ end
43
+
44
+ task :stop_all_peering, :roles => :peer do
45
+ run("pkill -f \"murder_client.py peer\"")
46
+ end
47
+ end
@@ -0,0 +1,121 @@
1
+ # Copyright 2010 Twitter, Inc.
2
+ # Copyright 2010 Larry Gadea <lg@twitter.com>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # no default defaults...
17
+ set :default_tag, ''
18
+ set :default_seeder_files_path, ''
19
+ set :default_destination_path, ''
20
+
21
+ # default remote dist path in app shared directory
22
+ set(:remote_murder_path) { "#{shared_path}/murder" }
23
+
24
+ namespace :murder do
25
+ task :create_torrent, :roles => :seeder do
26
+ require_tag
27
+ if !(seeder_files_path = (default_seeder_files_path if default_seeder_files_path != "") || ENV['files_path'])
28
+ puts "You must specify a 'files_path' parameter with the directory on the seeder which contains the files to distribute"
29
+ exit(1)
30
+ end
31
+
32
+ if ENV['path_is_file']
33
+ run "cp \"#{seeder_files_path}\" #{filename}"
34
+ else
35
+ run "tar -c -z -C #{seeder_files_path}/ -f #{filename} --exclude \".git*\" ."
36
+ end
37
+
38
+ tracker = find_servers(:roles => :tracker).first
39
+ tracker_host = tracker.host
40
+ tracker_port = variables[:tracker_port] || '8998'
41
+
42
+ run "python #{remote_murder_path}/murder_make_torrent.py '#{filename}' #{tracker_host}:#{tracker_port} '#{filename}.torrent'"
43
+
44
+ download_torrent unless ENV['do_not_download_torrent']
45
+ end
46
+
47
+ task :download_torrent, :roles => :seeder do
48
+ require_tag
49
+ download("#{filename}.torrent", "#{filename}.torrent", :via => :scp)
50
+ end
51
+
52
+ task :start_seeding, :roles => :seeder do
53
+ require_tag
54
+ run "screen -dms 'seeder-#{tag}' python #{remote_murder_path}/murder_client.py seeder '#{filename}.torrent' '#{filename}' `host $HOSTNAME | awk '{print $4}'`"
55
+ end
56
+
57
+ task :stop_seeding, :roles => :seeder do
58
+ require_tag
59
+ run("pkill -f \"SCREEN.*seeder-#{tag}\"")
60
+ end
61
+
62
+ task :peer, :roles => :peer do
63
+ require_tag
64
+
65
+ if !(destination_path = (default_destination_path if default_destination_path != "") || ENV['destination_path'])
66
+ puts "You must specify a 'destination_path' parameter with the directory in which to place transferred (and extract) files. Note that inside this directory, a new directory named by the tag will be created. It is inside of this second diectory that the files which the torrent was created from will be placed. To not create this second directory, pass in parameter 'no_tag_directory=1'"
67
+ exit(1)
68
+ end
69
+
70
+ if !ENV['no_tag_directory'] && !ENV['path_is_file']
71
+ destination_path += "/#{tag}"
72
+ end
73
+
74
+ if !ENV['path_is_file']
75
+ run "mkdir -p #{destination_path}/"
76
+ end
77
+
78
+ if ENV['unsafe_please_delete']
79
+ run "rm -rf '#{destination_path}/'*"
80
+ end
81
+ if !ENV['no_tag_directory'] && !ENV['path_is_file']
82
+ run "find '#{destination_path}/'* >/dev/null 2>&1 && echo \"destination_path #{destination_path} on $HOSTNAME is not empty\" && exit 1 || exit 0"
83
+ end
84
+
85
+ upload("#{filename}.torrent", "#{filename}.torrent", :via => :scp)
86
+ run "/usr/bin/time -f %e python #{remote_murder_path}/murder_client.py peer '#{filename}.torrent' '#{filename}' `host $CAPISTRANO:HOST$ | awk '{print $4}'`"
87
+
88
+ if ENV['path_is_file']
89
+ run "cp #{filename} #{destination_path}"
90
+ else
91
+ run "tar xf #{filename} -C #{destination_path}"
92
+ end
93
+ end
94
+
95
+ task :stop_peering, :roles => :peer do
96
+ require_tag
97
+ run("pkill -f \"murder_client.py peer.*#{filename}\"")
98
+ end
99
+
100
+ task :clean_temp_files, :roles => [:peer, :seeder] do
101
+ require_tag
102
+ run "rm -f #{filename} #{filename}.torrent || exit 0"
103
+ end
104
+
105
+ ###
106
+
107
+ def require_tag
108
+ if !(temp_tag = (default_tag if default_tag != "") || ENV['tag'])
109
+ puts "You must specify a 'tag' parameter to identify the transfer"
110
+ exit(1)
111
+ end
112
+
113
+ if (temp_tag.include?("/"))
114
+ puts "Tag cannot contain a / character"
115
+ exit(1)
116
+ end
117
+
118
+ set :tag, temp_tag
119
+ set :filename, "/tmp/#{tag}.tgz"
120
+ end
121
+ end
data/murder.gemspec ADDED
@@ -0,0 +1,101 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{murder}
8
+ s.version = "0.0.0.pre"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Larry Gadea"]
12
+ s.date = %q{2010-03-15}
13
+ s.description = %q{Large scale server deploys using BitTorrent and the BitTornado library}
14
+ s.email = %q{lg@twitter.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "dist/BitTornado/BT1/Choker.py",
26
+ "dist/BitTornado/BT1/Connecter.py",
27
+ "dist/BitTornado/BT1/Downloader.py",
28
+ "dist/BitTornado/BT1/DownloaderFeedback.py",
29
+ "dist/BitTornado/BT1/Encrypter.py",
30
+ "dist/BitTornado/BT1/FileSelector.py",
31
+ "dist/BitTornado/BT1/Filter.py",
32
+ "dist/BitTornado/BT1/HTTPDownloader.py",
33
+ "dist/BitTornado/BT1/NatCheck.py",
34
+ "dist/BitTornado/BT1/PiecePicker.py",
35
+ "dist/BitTornado/BT1/Rerequester.py",
36
+ "dist/BitTornado/BT1/Statistics.py",
37
+ "dist/BitTornado/BT1/Storage.py",
38
+ "dist/BitTornado/BT1/StorageWrapper.py",
39
+ "dist/BitTornado/BT1/StreamCheck.py",
40
+ "dist/BitTornado/BT1/T2T.py",
41
+ "dist/BitTornado/BT1/Uploader.py",
42
+ "dist/BitTornado/BT1/__init__.py",
43
+ "dist/BitTornado/BT1/btformats.py",
44
+ "dist/BitTornado/BT1/fakeopen.py",
45
+ "dist/BitTornado/BT1/makemetafile.py",
46
+ "dist/BitTornado/BT1/track.py",
47
+ "dist/BitTornado/ConfigDir.py",
48
+ "dist/BitTornado/ConfigReader.py",
49
+ "dist/BitTornado/ConnChoice.py",
50
+ "dist/BitTornado/CreateIcons.py",
51
+ "dist/BitTornado/CurrentRateMeasure.py",
52
+ "dist/BitTornado/HTTPHandler.py",
53
+ "dist/BitTornado/PSYCO.py",
54
+ "dist/BitTornado/RateLimiter.py",
55
+ "dist/BitTornado/RateMeasure.py",
56
+ "dist/BitTornado/RawServer.py",
57
+ "dist/BitTornado/ServerPortHandler.py",
58
+ "dist/BitTornado/SocketHandler.py",
59
+ "dist/BitTornado/__init__.py",
60
+ "dist/BitTornado/bencode.py",
61
+ "dist/BitTornado/bitfield.py",
62
+ "dist/BitTornado/clock.py",
63
+ "dist/BitTornado/download_bt1.py",
64
+ "dist/BitTornado/inifile.py",
65
+ "dist/BitTornado/iprangeparse.py",
66
+ "dist/BitTornado/launchmanycore.py",
67
+ "dist/BitTornado/natpunch.py",
68
+ "dist/BitTornado/parseargs.py",
69
+ "dist/BitTornado/parsedir.py",
70
+ "dist/BitTornado/piecebuffer.py",
71
+ "dist/BitTornado/selectpoll.py",
72
+ "dist/BitTornado/subnetparse.py",
73
+ "dist/BitTornado/torrentlistparse.py",
74
+ "dist/BitTornado/zurllib.py",
75
+ "dist/murder_client.py",
76
+ "dist/murder_make_torrent.py",
77
+ "dist/murder_tracker.py",
78
+ "doc/examples/Capfile",
79
+ "lib/capistrano/recipes/deploy/strategy/murder.rb",
80
+ "lib/murder.rb",
81
+ "lib/murder/admin.rb",
82
+ "lib/murder/murder.rb",
83
+ "murder.gemspec"
84
+ ]
85
+ s.homepage = %q{http://github.com/lg/murder}
86
+ s.rdoc_options = ["--charset=UTF-8"]
87
+ s.require_paths = ["lib"]
88
+ s.rubygems_version = %q{1.3.6}
89
+ s.summary = %q{Large scale server deploys using BitTorrent and the BitTornado library}
90
+
91
+ if s.respond_to? :specification_version then
92
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
93
+ s.specification_version = 3
94
+
95
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
96
+ else
97
+ end
98
+ else
99
+ end
100
+ end
101
+
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: murder
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ - pre
10
+ version: 0.0.0.pre
11
+ platform: ruby
12
+ authors:
13
+ - Larry Gadea
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-03-15 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Large scale server deploys using BitTorrent and the BitTornado library
23
+ email: lg@twitter.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - LICENSE
30
+ - README
31
+ files:
32
+ - .gitignore
33
+ - LICENSE
34
+ - README
35
+ - Rakefile
36
+ - VERSION
37
+ - dist/BitTornado/BT1/Choker.py
38
+ - dist/BitTornado/BT1/Connecter.py
39
+ - dist/BitTornado/BT1/Downloader.py
40
+ - dist/BitTornado/BT1/DownloaderFeedback.py
41
+ - dist/BitTornado/BT1/Encrypter.py
42
+ - dist/BitTornado/BT1/FileSelector.py
43
+ - dist/BitTornado/BT1/Filter.py
44
+ - dist/BitTornado/BT1/HTTPDownloader.py
45
+ - dist/BitTornado/BT1/NatCheck.py
46
+ - dist/BitTornado/BT1/PiecePicker.py
47
+ - dist/BitTornado/BT1/Rerequester.py
48
+ - dist/BitTornado/BT1/Statistics.py
49
+ - dist/BitTornado/BT1/Storage.py
50
+ - dist/BitTornado/BT1/StorageWrapper.py
51
+ - dist/BitTornado/BT1/StreamCheck.py
52
+ - dist/BitTornado/BT1/T2T.py
53
+ - dist/BitTornado/BT1/Uploader.py
54
+ - dist/BitTornado/BT1/__init__.py
55
+ - dist/BitTornado/BT1/btformats.py
56
+ - dist/BitTornado/BT1/fakeopen.py
57
+ - dist/BitTornado/BT1/makemetafile.py
58
+ - dist/BitTornado/BT1/track.py
59
+ - dist/BitTornado/ConfigDir.py
60
+ - dist/BitTornado/ConfigReader.py
61
+ - dist/BitTornado/ConnChoice.py
62
+ - dist/BitTornado/CreateIcons.py
63
+ - dist/BitTornado/CurrentRateMeasure.py
64
+ - dist/BitTornado/HTTPHandler.py
65
+ - dist/BitTornado/PSYCO.py
66
+ - dist/BitTornado/RateLimiter.py
67
+ - dist/BitTornado/RateMeasure.py
68
+ - dist/BitTornado/RawServer.py
69
+ - dist/BitTornado/ServerPortHandler.py
70
+ - dist/BitTornado/SocketHandler.py
71
+ - dist/BitTornado/__init__.py
72
+ - dist/BitTornado/bencode.py
73
+ - dist/BitTornado/bitfield.py
74
+ - dist/BitTornado/clock.py
75
+ - dist/BitTornado/download_bt1.py
76
+ - dist/BitTornado/inifile.py
77
+ - dist/BitTornado/iprangeparse.py
78
+ - dist/BitTornado/launchmanycore.py
79
+ - dist/BitTornado/natpunch.py
80
+ - dist/BitTornado/parseargs.py
81
+ - dist/BitTornado/parsedir.py
82
+ - dist/BitTornado/piecebuffer.py
83
+ - dist/BitTornado/selectpoll.py
84
+ - dist/BitTornado/subnetparse.py
85
+ - dist/BitTornado/torrentlistparse.py
86
+ - dist/BitTornado/zurllib.py
87
+ - dist/murder_client.py
88
+ - dist/murder_make_torrent.py
89
+ - dist/murder_tracker.py
90
+ - doc/examples/Capfile
91
+ - lib/capistrano/recipes/deploy/strategy/murder.rb
92
+ - lib/murder.rb
93
+ - lib/murder/admin.rb
94
+ - lib/murder/murder.rb
95
+ - murder.gemspec
96
+ has_rdoc: true
97
+ homepage: http://github.com/lg/murder
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">"
115
+ - !ruby/object:Gem::Version
116
+ segments:
117
+ - 1
118
+ - 3
119
+ - 1
120
+ version: 1.3.1
121
+ requirements: []
122
+
123
+ rubyforge_project:
124
+ rubygems_version: 1.3.6
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Large scale server deploys using BitTorrent and the BitTornado library
128
+ test_files: []
129
+