swiftiply 0.6.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS +2 -0
  3. data/README.md +62 -0
  4. data/bin/{mongrel_rails → evented_mongrel_rails} +6 -14
  5. data/bin/swiftiplied_mongrel_rails +246 -0
  6. data/bin/swiftiply +136 -116
  7. data/bin/swiftiply_mongrel_rails +2 -2
  8. data/bin/swiftiplyctl +283 -0
  9. data/cleanup.sh +5 -0
  10. data/ext/deque/extconf.rb +162 -0
  11. data/ext/deque/swiftcore/rubymain.cpp +435 -0
  12. data/ext/fastfilereader/extconf.rb +2 -2
  13. data/ext/fastfilereader/mapper.cpp +2 -0
  14. data/ext/map/extconf.rb +161 -0
  15. data/ext/map/rubymain.cpp +500 -0
  16. data/ext/splaytree/extconf.rb +161 -0
  17. data/ext/splaytree/swiftcore/rubymain.cpp +580 -0
  18. data/ext/splaytree/swiftcore/splay_map.h +635 -0
  19. data/ext/splaytree/swiftcore/splay_set.h +575 -0
  20. data/ext/splaytree/swiftcore/splay_tree.h +1127 -0
  21. data/external/httpclient.rb +231 -0
  22. data/external/package.rb +13 -13
  23. data/setup.rb +18 -2
  24. data/src/swiftcore/Swiftiply.rb +417 -773
  25. data/src/swiftcore/Swiftiply/backend_protocol.rb +213 -0
  26. data/src/swiftcore/Swiftiply/cache_base.rb +49 -0
  27. data/src/swiftcore/Swiftiply/cache_base_mixin.rb +52 -0
  28. data/src/swiftcore/Swiftiply/cluster_managers/rest_based_cluster_manager.rb +9 -0
  29. data/src/swiftcore/Swiftiply/cluster_protocol.rb +70 -0
  30. data/src/swiftcore/Swiftiply/config.rb +370 -0
  31. data/src/swiftcore/Swiftiply/config/rest_updater.rb +26 -0
  32. data/src/swiftcore/Swiftiply/constants.rb +101 -0
  33. data/src/swiftcore/Swiftiply/content_cache_entry.rb +44 -0
  34. data/src/swiftcore/Swiftiply/content_response.rb +45 -0
  35. data/src/swiftcore/Swiftiply/control_protocol.rb +49 -0
  36. data/src/swiftcore/Swiftiply/dynamic_request_cache.rb +41 -0
  37. data/src/swiftcore/Swiftiply/etag_cache.rb +64 -0
  38. data/src/swiftcore/Swiftiply/file_cache.rb +46 -0
  39. data/src/swiftcore/Swiftiply/hash_cache_base.rb +22 -0
  40. data/src/swiftcore/Swiftiply/http_recognizer.rb +267 -0
  41. data/src/swiftcore/Swiftiply/loggers/Analogger.rb +21 -0
  42. data/src/swiftcore/Swiftiply/loggers/stderror.rb +13 -0
  43. data/src/swiftcore/Swiftiply/mocklog.rb +10 -0
  44. data/src/swiftcore/Swiftiply/proxy.rb +15 -0
  45. data/src/swiftcore/Swiftiply/proxy_backends/keepalive.rb +286 -0
  46. data/src/swiftcore/Swiftiply/proxy_backends/traditional.rb +286 -0
  47. data/src/swiftcore/Swiftiply/proxy_backends/traditional/redis_directory.rb +87 -0
  48. data/src/swiftcore/Swiftiply/proxy_backends/traditional/static_directory.rb +69 -0
  49. data/src/swiftcore/Swiftiply/proxy_bag.rb +716 -0
  50. data/src/swiftcore/Swiftiply/rest_based_cluster_manager.rb +15 -0
  51. data/src/swiftcore/Swiftiply/splay_cache_base.rb +21 -0
  52. data/src/swiftcore/Swiftiply/support_pagecache.rb +6 -3
  53. data/src/swiftcore/Swiftiply/swiftiply_2_http_proxy.rb +7 -0
  54. data/src/swiftcore/Swiftiply/swiftiply_client.rb +20 -5
  55. data/src/swiftcore/Swiftiply/version.rb +5 -0
  56. data/src/swiftcore/evented_mongrel.rb +26 -8
  57. data/src/swiftcore/hash.rb +43 -0
  58. data/src/swiftcore/method_builder.rb +28 -0
  59. data/src/swiftcore/streamer.rb +46 -0
  60. data/src/swiftcore/swiftiplied_mongrel.rb +91 -23
  61. data/src/swiftcore/types.rb +20 -3
  62. data/swiftiply.gemspec +14 -8
  63. data/test/TC_Deque.rb +152 -0
  64. data/test/TC_ProxyBag.rb +147 -166
  65. data/test/TC_Swiftiply.rb +576 -169
  66. data/test/TC_Swiftiply/mongrel/evented_hello.rb +1 -1
  67. data/test/TC_Swiftiply/mongrel/swiftiplied_hello.rb +1 -1
  68. data/test/TC_Swiftiply/test_serve_static_file_xsendfile/sendfile_client.rb +27 -0
  69. data/test/TC_Swiftiply/test_ssl/bin/validate_ssl_capability.rb +21 -0
  70. data/test/TC_Swiftiply/test_ssl/test.cert +16 -0
  71. data/test/TC_Swiftiply/test_ssl/test.key +15 -0
  72. data/{bin → test/bin}/echo_client +0 -0
  73. metadata +136 -94
  74. data/README +0 -126
  75. data/ext/swiftiply_parse/parse.rl +0 -90
@@ -30,8 +30,8 @@ class MongrelSwiftStart
30
30
  opts.on('-n','--num-mongrels [NUM]','The number of mongrels to start.') do |numm|
31
31
  config[:num] = numm.to_i
32
32
  end
33
- opts.on('-P','--pidfiles [NUM]','Path to store PID files.') do |numm|
34
- config[:num] = numm.to_i
33
+ opts.on('-P','--pidfiles [NUM]','Path to store PID files.') do |pid|
34
+ config[:pid] = pid.to_i
35
35
  end
36
36
  end.parse!
37
37
  @config = defaults.update(config)
data/bin/swiftiplyctl ADDED
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'socket'
5
+ require 'yaml'
6
+
7
+ ENV['SWIFT'] = 'true'
8
+
9
+ class ServerInstance
10
+ attr_accessor :instances,:location,:online,:port
11
+
12
+ def initialize(port,options = {})
13
+ self.instances = options.delete(:instances)
14
+ self.location = options.delete(:location)
15
+ self.port = port
16
+ begin
17
+ TCPSocket.open('127.0.0.1',self.port).close
18
+ self.online = true
19
+ rescue Errno::ECONNREFUSED
20
+ self.online = false
21
+ end
22
+ end
23
+
24
+ def log(msg)
25
+ STDERR.print msg
26
+ end
27
+ end
28
+
29
+ class MongrelInstance < ServerInstance
30
+ attr_accessor :pid_cache
31
+
32
+ def add
33
+ log "Adding #{self.instances} Mongrel instance#{'s' unless self.instances == 1}\n"
34
+ self.launch_instances
35
+ log "\n"
36
+ end
37
+
38
+ def initialize(*args)
39
+ super
40
+ self.online = !self.pids.empty?
41
+ end
42
+
43
+ def launch_instances
44
+ size = self.pids.size
45
+ self.instances.times do |i|
46
+ pid = size+i
47
+ # I know we specified env['swift'] above, but hey, it never hurts to double-check
48
+ `env SWIFT=1 mongrel_rails start -c #{self.location} -p #{self.port} -d -P #{File.join(self.location,'log',"dog#{pid.to_s.rjust(3,"0")}.pid")}`
49
+ sleep 1
50
+ log "Mongrel instance ##{pid+1} started#{"\n" unless i+1 == self.instances}"
51
+ end
52
+ end
53
+
54
+ def pids
55
+ self.pid_cache ||= Dir.glob(File.join(self.location,'log','dog*.pid')).sort
56
+ end
57
+
58
+ def remove
59
+ log "Shaving #{self.instances} Mongrel instance#{'s' unless self.instances == 1} from the stack... "
60
+ if self.pids.empty?
61
+ log "No Mongrel instances!"
62
+ else
63
+ self.instances.times do |i|
64
+ self.stop_instance(self.pids.pop)
65
+ end
66
+ log "Done!"
67
+ end
68
+ log "\n"
69
+ end
70
+
71
+ def start
72
+ log "Starting #{self.instances} Mongrel instance#{'s' unless self.instances == 1} on port #{self.port}... "
73
+ if !self.pids.empty?
74
+ log 'Mongrel already started'
75
+ else
76
+ log "\n"
77
+ self.launch_instances
78
+ end
79
+ log "\n"
80
+ end
81
+
82
+ def status
83
+ log "Mongrel: #{self.online ? "\033[1;32mOnline\033[00m
84
+ Instances: \033[1;32m#{self.pids.size}\033[00m" : "\033[1;31mOffline\033[00m"}\n"
85
+ end
86
+
87
+ def stop
88
+ log 'Shutting down Mongrel... '
89
+ # We work based on pids b/c Swiftiplied Mongrel instances don't reply to TCPSocket connections for some reason
90
+ if !self.pids.empty?
91
+ for pid in self.pids
92
+ self.stop_instance(pid)
93
+ end
94
+ log 'Done!'
95
+ else
96
+ log "No active Mongrel instance#{'s' unless self.instances == 1} on port #{self.port}"
97
+ end
98
+ log "\n"
99
+ end
100
+
101
+ def stop_instance(pid)
102
+ Process.kill("KILL",File.read(pid).to_i)
103
+ File.unlink(pid)
104
+ sleep 1
105
+ end
106
+ end
107
+
108
+ class SwiftiplyInstance < ServerInstance
109
+ attr_accessor :pid
110
+
111
+ def initialize(*args)
112
+ super
113
+ self.pid = `pgrep -f 'swiftiply -c #{File.expand_path(File.join(self.location,'config','swiftiply.yml'))}'`
114
+ self.online = self.pid != ""
115
+ end
116
+
117
+ def start
118
+ log "Starting Swiftiply instance on port #{self.port}... "
119
+ if self.online
120
+ log 'Swiftiply already started'
121
+ else
122
+ # Okay, Swiftiply actually switched pids on me regularly, so I'm going a different route with this one...
123
+ IO.popen("swiftiply -c #{File.expand_path(File.join(self.location,'config','swiftiply.yml'))}")
124
+ log 'Done!'
125
+ end
126
+ log "\n"
127
+ end
128
+
129
+ def status
130
+ log "Swiftiply: #{self.online ? "\033[1;32mOnline\033[00m" : "\033[1;31mOffline\033[00m"}\n"
131
+ end
132
+
133
+ def stop
134
+ log 'Shutting down Swiftiply... '
135
+ if self.online
136
+ Process.kill("KILL",self.pid.to_i)
137
+ sleep 1
138
+ log 'Done!'
139
+ else
140
+ log "No active Swiftiply instance on port #{self.port}"
141
+ end
142
+ log "\n"
143
+ end
144
+ end
145
+
146
+ class SwiftiplyControl
147
+ def self.load_config
148
+ if @command =~ /(status_all)/
149
+ @mongrel_pids = `pgrep -l -f 'mongrel'`.split("\n")
150
+ @swift_pids = `pgrep -l -f 'swiftiply'`.split("\n")
151
+ elsif File.exists?(@location)
152
+ config_dir = File.join(@location,'config')
153
+ yml_path = File.join(config_dir,'swiftiply.yml')
154
+ if File.exists?(yml_path)
155
+ yaml = YAML::load(File.open(yml_path))
156
+ @mongrel = MongrelInstance.new(yaml["map"].first["outgoing"].split(":").last.strip,:instances => (@config[:instances] || yaml["n"]).to_i,:location => @location)
157
+ @swiftiply = SwiftiplyInstance.new(yaml["cluster_port"],:location => @location)
158
+ else
159
+ response = ""
160
+ while response !~ /(Y|n)/
161
+ log "No swiftiply.yml file found in #{File.join(@dir || ".",'config')}. Would you like to generate one now? [Yn] "
162
+ response = STDIN.gets.chomp
163
+ end
164
+ @config[:instances] = "2" unless @config[:instances].to_i > 0
165
+ if response == 'Y'
166
+ Dir.mkdir(config_dir) unless File.exists?(config_dir)
167
+ yaml = "cluster_address: 127.0.0.1
168
+ cluster_port: 3000
169
+ daemonize: true
170
+ epoll: true
171
+ epoll_descriptors: 8192
172
+ map:
173
+ - incoming: localhost
174
+ outgoing: 127.0.0.1:5000
175
+ default: true
176
+ docroot: #{@location}
177
+ redeployable: true
178
+ n: #{@config[:instances]}"
179
+ file = File.open(yml_path,'w+')
180
+ file.write(yaml)
181
+ file.close
182
+ self.load_config
183
+ else
184
+ exit!
185
+ end
186
+ end
187
+ else
188
+ log "No site found at #{@location}\n"
189
+ exit!
190
+ end
191
+ end
192
+
193
+ def self.log(msg)
194
+ STDERR.print msg
195
+ end
196
+
197
+ def self.parse_options(config = {})
198
+ defaults = {}
199
+ OptionParser.new do |opts|
200
+ opts.banner = 'Usage: swiftiply_config <command> [options]'
201
+ opts.separator ''
202
+ opts.on('-n','--num-mongrels [NUM]','The number of mongrels to start.') do |num|
203
+ config[:instances] = num
204
+ end
205
+ end.parse!
206
+ @config = defaults.update(config)
207
+ if @command
208
+ @dir = ARGV.shift
209
+ @location = @dir.nil? ? Dir.pwd : @dir[0,1] == "/" ? @dir : File.join(Dir.pwd,@dir)
210
+ self.load_config
211
+ end
212
+ end
213
+
214
+ def self.run
215
+ @command = ARGV.shift
216
+ parse_options
217
+ case @command
218
+ when "add_mongrel"
219
+ @mongrel.instances = (@config[:instances] || "1").to_i
220
+ @mongrel.add
221
+ when "remove_mongrel"
222
+ @mongrel.instances = (@config[:instances] || "1").to_i
223
+ @mongrel.remove
224
+ when "restart"
225
+ @mongrel.stop
226
+ @mongrel.start
227
+ @swiftiply.stop
228
+ @swiftiply.start
229
+ when "restart_mongrel"
230
+ @mongrel.stop
231
+ @mongrel.start
232
+ when "restart_swift"
233
+ @swiftiply.stop
234
+ @swiftiply.start
235
+ when "start"
236
+ @mongrel.start
237
+ @swiftiply.start
238
+ when "start_mongrel"
239
+ @mongrel.start
240
+ when "start_swift"
241
+ @swiftiply.start
242
+ when "status"
243
+ @mongrel.status
244
+ @swiftiply.status
245
+ when "status_all"
246
+ pids = [@swift_pids.select{|pid| pid =~ /swiftiply -c (.+)$/}.collect{|pid| pid.slice(/swiftiply -c (.+)$/).gsub(/(swiftiply -c |\/config\/swiftiply\.yml)/,'')},@mongrel_pids.select{|pid| pid =~ /-c ([^ ]+) /}.collect{|pid| File.expand_path(pid.match(/-c ([^ ]+) /)[1].strip + "/")}].flatten.uniq.compact.sort
247
+ for server in pids
248
+ log "#{server}\n"
249
+ `swift status #{server}`
250
+ log "\n"
251
+ end
252
+ when "stop"
253
+ @mongrel.stop
254
+ @swiftiply.stop
255
+ when "stop_mongrel"
256
+ @mongrel.stop
257
+ when "stop_swift"
258
+ @swiftiply.stop
259
+ else
260
+ log "#{@command} is not a valid command\n" unless @command.nil?
261
+ log "Usage: swiftiply_ctl <command> [options]
262
+ Available commands are:
263
+
264
+ - add_mongrel
265
+ - remove_mongrel
266
+ - restart
267
+ - restart_mongrel
268
+ - restart_swift
269
+ - start
270
+ - start_mongrel
271
+ - start_swift
272
+ - status
273
+ - stop
274
+ - stop_mongrel
275
+ - stop_swift
276
+
277
+ Each command takes -h as an option to get help.
278
+ "
279
+ end
280
+ end
281
+ end
282
+
283
+ SwiftiplyControl.run
data/cleanup.sh ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ rm ext/*/*.*o
3
+ rm ext/*/*.*bundle
4
+ rm ext/*/*.log
5
+ rm ext/*/Makefile
@@ -0,0 +1,162 @@
1
+ # $Id: extconf.rb 4526 2007-07-03 18:04:34Z francis $
2
+ #
3
+ #----------------------------------------------------------------------------
4
+ #
5
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
6
+ # Gmail: garbagecat10
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of either: 1) the GNU General Public License
10
+ # as published by the Free Software Foundation; either version 2 of the
11
+ # License, or (at your option) any later version; or 2) Ruby's License.
12
+ #
13
+ # See the file COPYING for complete licensing information.
14
+ #
15
+ #---------------------------------------------------------------------------
16
+ #
17
+ # extconf.rb for Fast File Reader
18
+ # We have to munge LDSHARED because this code needs a C++ link.
19
+ #
20
+
21
+ require 'mkmf'
22
+
23
+ flags = []
24
+
25
+ case RUBY_PLATFORM.split('-',2)[1]
26
+ when 'mswin32', 'mingw32', 'bccwin32'
27
+ unless have_header('windows.h') and
28
+ have_header('winsock.h') and
29
+ have_library('kernel32') and
30
+ have_library('rpcrt4') and
31
+ have_library('gdi32')
32
+ exit
33
+ end
34
+
35
+ flags << "-D OS_WIN32"
36
+ flags << '-D BUILD_FOR_RUBY'
37
+ flags << "-EHs"
38
+ flags << "-GR"
39
+
40
+ # dir_config('ssl')
41
+ # if have_library('ssleay32') and
42
+ # have_library('libeay32') and
43
+ # have_header('openssl/ssl.h') and
44
+ # have_header('openssl/err.h')
45
+ # flags << '-D WITH_SSL'
46
+ # else
47
+ # flags << '-D WITHOUT_SSL'
48
+ # end
49
+
50
+ when /solaris/
51
+ # unless have_library('pthread') and
52
+ # have_library('nsl') and
53
+ # have_library('socket')
54
+ # exit
55
+ # end
56
+
57
+ flags << '-D OS_UNIX'
58
+ flags << '-D OS_SOLARIS8'
59
+ flags << '-D BUILD_FOR_RUBY'
60
+
61
+ # dir_config('ssl')
62
+ # if have_library('ssl') and
63
+ # have_library('crypto') and
64
+ # have_header('openssl/ssl.h') and
65
+ # have_header('openssl/err.h')
66
+ # flags << '-D WITH_SSL'
67
+ # else
68
+ # flags << '-D WITHOUT_SSL'
69
+ # end
70
+
71
+ # on Unix we need a g++ link, not gcc.
72
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
73
+
74
+ when /darwin/
75
+ flags << '-DOS_UNIX'
76
+ flags << '-DBUILD_FOR_RUBY'
77
+
78
+ # dir_config('ssl')
79
+ # if have_library('ssl') and
80
+ # have_library('crypto') and
81
+ # have_library('C') and
82
+ # have_header('openssl/ssl.h') and
83
+ # have_header('openssl/err.h')
84
+ # flags << '-DWITH_SSL'
85
+ # else
86
+ # flags << '-DWITHOUT_SSL'
87
+ # end
88
+ # on Unix we need a g++ link, not gcc.
89
+ # Ff line contributed by Daniel Harple.
90
+ CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
91
+
92
+ when /linux/
93
+ unless have_library('pthread')
94
+ exit
95
+ end
96
+
97
+ flags << '-DOS_UNIX'
98
+ flags << '-DBUILD_FOR_RUBY'
99
+
100
+ # Original epoll test is inadequate because 2.4 kernels have the header
101
+ # but not the code.
102
+ # #flags << '-DHAVE_EPOLL' if have_header('sys/epoll.h')
103
+ # if have_header('sys/epoll.h')
104
+ # File.open("hasEpollTest.c", "w") {|f|
105
+ # f.puts "#include <sys/epoll.h>"
106
+ # f.puts "int main() { epoll_create(1024); return 0;}"
107
+ # }
108
+ # (e = system( "gcc hasEpollTest.c -o hasEpollTest " )) and (e = $?.to_i)
109
+ # `rm -f hasEpollTest.c hasEpollTest`
110
+ # flags << '-DHAVE_EPOLL' if e == 0
111
+ # end
112
+ #
113
+ # dir_config('ssl')
114
+ # if have_library('ssl') and
115
+ # have_library('crypto') and
116
+ # have_header('openssl/ssl.h') and
117
+ # have_header('openssl/err.h')
118
+ # flags << '-DWITH_SSL'
119
+ # else
120
+ # flags << '-DWITHOUT_SSL'
121
+ # end
122
+ # on Unix we need a g++ link, not gcc.
123
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
124
+
125
+ # Modify the mkmf constant LINK_SO so the generated shared object is stripped.
126
+ # You might think modifying CONFIG['LINK_SO'] would be a better way to do this,
127
+ # but it doesn't work because mkmf doesn't look at CONFIG['LINK_SO'] again after
128
+ # it initializes.
129
+ #linkso = Object.send :remove_const, "LINK_SO"
130
+ #LINK_SO = linkso + "; strip $@"
131
+
132
+ else
133
+ # unless have_library('pthread')
134
+ # exit
135
+ # end
136
+
137
+ flags << '-DOS_UNIX'
138
+ flags << '-DBUILD_FOR_RUBY'
139
+
140
+ # dir_config('ssl')
141
+ # if have_library('ssl') and
142
+ # have_library('crypto') and
143
+ # have_header('openssl/ssl.h') and
144
+ # have_header('openssl/err.h')
145
+ # flags << '-DWITH_SSL'
146
+ # else
147
+ # flags << '-DWITHOUT_SSL'
148
+ # end
149
+ # on Unix we need a g++ link, not gcc.
150
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
151
+
152
+ end
153
+
154
+ if $CPPFLAGS
155
+ $CPPFLAGS += ' ' + flags.join(' ')
156
+ else
157
+ $CFLAGS += ' ' + flags.join(' ')
158
+ end
159
+
160
+
161
+ #create_makefile("deque","swiftcore")
162
+ create_makefile("swiftcore/deque","swiftcore")