zbatery 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/zbatery.rb ADDED
@@ -0,0 +1,154 @@
1
+ # -*- encoding: binary -*-
2
+ require 'rainbows'
3
+
4
+ module Zbatery
5
+
6
+ # current version of Zbatery
7
+ VERSION = "0.0.0"
8
+
9
+ class << self
10
+
11
+ # runs the Zbatery HttpServer with +app+ and +options+ and does
12
+ # not return until the server has exited.
13
+ def run(app, options = {})
14
+ HttpServer.new(app, options).start.join
15
+ end
16
+ end
17
+
18
+ Rainbows::Const::RACK_DEFAULTS["SERVER_SOFTWARE"] = "Zbatery #{VERSION}"
19
+
20
+ # true if our Ruby implementation supports unlinked files
21
+ UnlinkedIO = begin
22
+ tmp = Unicorn::Util.tmpio
23
+ tmp.chmod(0)
24
+ tmp.close
25
+ true
26
+ rescue
27
+ false
28
+ end
29
+
30
+ # we don't actually fork workers, but allow using the
31
+ # {before,after}_fork hooks found in Unicorn/Rainbows!
32
+ # config files...
33
+ FORK_HOOK = lambda { |_,_| }
34
+
35
+ class HttpServer < Rainbows::HttpServer
36
+
37
+ # only used if no concurrency model is specified
38
+ def worker_loop(worker)
39
+ init_worker_process(worker)
40
+ begin
41
+ ret = IO.select(LISTENERS, nil, nil, nil) and
42
+ ret.first.each do |sock|
43
+ begin
44
+ process_client(sock.accept_nonblock)
45
+ rescue Errno::EAGAIN, Errno::ECONNABORTED
46
+ end
47
+ end
48
+ rescue Errno::EINTR
49
+ rescue Errno::EBADF, TypeError
50
+ break
51
+ rescue => e
52
+ Rainbows::Error.listen_loop(e)
53
+ end while G.alive
54
+ end
55
+
56
+ # no-op
57
+ def maintain_worker_count; end
58
+
59
+ # can't just do a graceful exit if reopening logs fails, so we just
60
+ # continue on...
61
+ def reopen_logs
62
+ logger.info "reopening logs"
63
+ Unicorn::Util.reopen_logs
64
+ logger.info "done reopening logs"
65
+ rescue => e
66
+ logger.error "failed reopening logs #{e.message}"
67
+ end
68
+
69
+ def join
70
+ begin
71
+ trap(:INT) { stop(false) } # Mongrel trapped INT for Win32...
72
+
73
+ # try these anyways regardless of platform...
74
+ trap(:TERM) { stop(false) }
75
+ trap(:QUIT) { stop }
76
+ trap(:USR1) { reopen_logs }
77
+ trap(:USR2) { reexec }
78
+
79
+ # no other way to reliably switch concurrency models...
80
+ trap(:HUP) { reexec; stop }
81
+
82
+ # technically feasible in some cases, just not sanely supportable:
83
+ %w(TTIN TTOU WINCH).each do |sig|
84
+ trap(sig) { logger.info "SIG#{sig} is not handled by Zbatery" }
85
+ end
86
+ rescue => e # hopefully ignores errors on Win32...
87
+ logger.error "failed to setup signal handler: #{e.message}"
88
+ end
89
+ worker = Worker.new(0, $stdout)
90
+ before_fork.call(self, worker)
91
+ worker_loop(worker) # runs forever
92
+ end
93
+
94
+ def stop(graceful = true)
95
+ Rainbows::G.quit!
96
+ exit!(0) unless graceful
97
+ end
98
+
99
+ def before_fork
100
+ hook = super
101
+ hook == FORK_HOOK or
102
+ logger.warn "calling before_fork without forking"
103
+ hook
104
+ end
105
+
106
+ def after_fork
107
+ hook = super
108
+ hook == FORK_HOOK or
109
+ logger.warn "calling after_fork without having forked"
110
+ hook
111
+ end
112
+ end
113
+ end
114
+
115
+ # :stopdoc:
116
+ # override stuff we don't need or can't use portably
117
+ module Rainbows
118
+
119
+ module Base
120
+ # master == worker in our case
121
+ def init_worker_process(worker)
122
+ after_fork.call(self, worker)
123
+ build_app! unless preload_app
124
+ logger.info "Zbatery #@use worker_connections=#@worker_connections"
125
+ end
126
+ end
127
+
128
+ # we can't/don't need to do the fchmod heartbeat Unicorn/Rainbows! does
129
+ def G.tick
130
+ alive
131
+ end
132
+ end
133
+
134
+ module Unicorn
135
+
136
+ class Configurator
137
+ DEFAULTS[:before_fork] = DEFAULTS[:after_fork] = Zbatery::FORK_HOOK
138
+ end
139
+
140
+ unless Zbatery::UnlinkedIO
141
+ require 'tempfile'
142
+ class Util
143
+
144
+ # Tempfiles should get automatically unlinked by GC
145
+ def self.tmpio
146
+ fp = Tempfile.new("zbatery")
147
+ fp.binmode
148
+ fp.sync = true
149
+ fp
150
+ end
151
+ end
152
+ end
153
+
154
+ end
data/local.mk.sample ADDED
@@ -0,0 +1,78 @@
1
+
2
+ # this is the local.mk file used by Eric Wong on his dev boxes.
3
+ # GNUmakefile will source local.mk in the top-level source tree
4
+ # if it is present.
5
+ #
6
+ # This is depends on a bunch of GNU-isms from bash, sed, touch.
7
+
8
+ RSYNC = rsync
9
+ DLEXT := so
10
+ gems := rack-1.0.1
11
+ # gems += unicorn-0.95.2 # installed via setup.rb
12
+ # gems += rainbows-0.8.0 # installed via setup.rb
13
+ gems += rev-0.3.1
14
+ gems += iobuffer-0.1.1
15
+ gems += eventmachine-0.12.10
16
+ gems += async_sinatra-0.1.5 sinatra-0.9.4
17
+
18
+ # Avoid loading rubygems to speed up tests because gmake is
19
+ # fork+exec heavy with Ruby.
20
+ prefix = $(HOME)
21
+ ifeq ($(r19),)
22
+ RUBY := $(prefix)/bin/ruby
23
+ gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.8/gems/,$(gems))
24
+ else
25
+ prefix := $(prefix)/ruby-1.9
26
+ export PATH := $(prefix)/bin:$(PATH)
27
+ RUBY := $(prefix)/bin/ruby --disable-gems
28
+ gems += case-0.5 revactor-0.1.5
29
+ gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.9.1/gems/,$(gems))
30
+ endif
31
+
32
+ ifdef gem_paths
33
+ sp :=
34
+ sp +=
35
+ export RUBYLIB := $(subst $(sp),:,$(addsuffix /lib,$(gem_paths)))
36
+ endif
37
+
38
+ # pipefail is THE reason to use bash (v3+) or never revisions of ksh93
39
+ # SHELL := /bin/bash -e -o pipefail
40
+ SHELL := /bin/ksh93 -e -o pipefail
41
+
42
+ # trace execution of tests
43
+ # TRACER = strace -f -o $(t_pfx).strace -s 100000
44
+ TRACER = /usr/bin/time -v -o $(t_pfx).time
45
+
46
+ full-test: test-18 test-19
47
+ test-18:
48
+ $(MAKE) test 2>&1 | sed -e 's!^!1.8 !'
49
+ test-19:
50
+ $(MAKE) test r19=t 2>&1 | sed -e 's!^!1.9 !'
51
+
52
+ latest: NEWS
53
+ @awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' < $<
54
+
55
+ # publishes docs to http://zbatery.bogomip.org/
56
+ publish_doc:
57
+ -git set-file-times
58
+ $(RM) -r doc ChangeLog NEWS
59
+ $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
60
+ $(MAKE) -s latest > doc/LATEST
61
+ find doc/images doc/js -type f | \
62
+ TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
63
+ $(MAKE) doc_gz
64
+ chmod 644 $$(find doc -type f)
65
+ $(RSYNC) -av doc/ dcvr:/srv/zbatery/
66
+ git ls-files | xargs touch
67
+
68
+ # Create gzip variants of the same timestamp as the original so nginx
69
+ # "gzip_static on" can serve the gzipped versions directly.
70
+ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
71
+ doc_gz:
72
+ touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
73
+ for i in $(docs); do \
74
+ gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
75
+
76
+ # launches any of the following shells with RUBYLIB set
77
+ irb sh bash ksh:
78
+ $@
@@ -0,0 +1,187 @@
1
+ .TH zbatery 1 "December 9, 2009" "Zbatery User Manual"
2
+ .SH NAME
3
+ .PP
4
+ zbatery - rackup-like command to launch Zbatery
5
+ .SH SYNOPSIS
6
+ .PP
7
+ zbatery [-c CONFIG_FILE] [-E RACK_ENV] [-D] [RACKUP_FILE]
8
+ .SH DESCRIPTION
9
+ .PP
10
+ A rackup(1)-like command to launch Rack applications using Zbatery.
11
+ It is expected to be started in your application root (APP_ROOT),
12
+ but \[lq]Dir.chdir\[rq] may also be executed in the CONFIG_FILE or
13
+ RACKUP_FILE.
14
+ .PP
15
+ While Zbatery takes a myriad of command-line options for
16
+ compatibility with ruby(1) and rackup(1), it is recommended to
17
+ stick to the few command-line options specified in the SYNOPSIS and
18
+ use the CONFIG_FILE as much as possible.
19
+ .SH RACKUP FILE
20
+ .PP
21
+ This defaults to "config.ru" in APP_ROOT.
22
+ It should be the same file used by rackup(1) and other Rack
23
+ launchers, it uses the \f[I]Rack::Builder\f[] DSL.
24
+ .PP
25
+ Embedded command-line options are mostly parsed for compatibility
26
+ with rackup(1) but strongly discouraged.
27
+ .SH UNICORN OPTIONS
28
+ .TP
29
+ .B -c, --config-file CONFIG_FILE
30
+ Path to the Unicorn-specific config file.
31
+ The config file is implemented as a Ruby DSL, so Ruby code may
32
+ executed (e.g.
33
+ \[lq]Dir.chdir\[rq], \[lq]Process::UID.change_privilege\[rq]).
34
+ See the RDoc/ri for the \f[I]Unicorn::Configurator\f[] class for
35
+ the full list of directives available from the DSL.
36
+ .RS
37
+ .RE
38
+ .TP
39
+ .B -D, --daemonize
40
+ Run daemonized in the background.
41
+ The process is detached from the controlling terminal and stdin is
42
+ redirected to \[lq]/dev/null\[rq].
43
+ Unlike many common UNIX daemons, we do not chdir to "/" upon
44
+ daemonization to allow more control over the startup/upgrade
45
+ process.
46
+ Unless specified in the CONFIG_FILE, stderr and stdout will also be
47
+ redirected to \[lq]/dev/null\[rq].
48
+ .RS
49
+ .RE
50
+ .TP
51
+ .B -E, --env RACK_ENV
52
+ Run under the given RACK_ENV.
53
+ See the RACK ENVIRONMENT section for more details.
54
+ .RS
55
+ .RE
56
+ .TP
57
+ .B -l, --listen ADDRESS
58
+ Listens on a given ADDRESS.
59
+ ADDRESS may be in the form of HOST:PORT or PATH, HOST:PORT is taken
60
+ to mean a TCP socket and PATH is meant to be a path to a UNIX
61
+ domain socket.
62
+ Defaults to \[lq]0.0.0.0:8080\[rq] (all addresses on TCP port 8080)
63
+ For production deployments, specifying the \[lq]listen\[rq]
64
+ directive in CONFIG_FILE is recommended as it allows fine-tuning of
65
+ socket options.
66
+ .RS
67
+ .RE
68
+ .SH RACKUP COMPATIBILITY OPTIONS
69
+ .TP
70
+ .B -o, --host HOST
71
+ Listen on a TCP socket belonging to HOST, default is
72
+ \[lq]0.0.0.0\[rq] (all addresses).
73
+ If specified multiple times on the command-line, only the
74
+ last-specified value takes effect.
75
+ This option only exists for compatibility with the rackup(1)
76
+ command, use of \[lq]-l\[rq]/\[lq]--listen\[rq] switch is
77
+ recommended instead.
78
+ .RS
79
+ .RE
80
+ .TP
81
+ .B -p, --port PORT
82
+ Listen on the specified TCP PORT, default is 8080.
83
+ If specified multiple times on the command-line, only the
84
+ last-specified value takes effect.
85
+ This option only exists for compatibility with the rackup(1)
86
+ command, use of \[lq]-l\[rq]/\[lq]--listen\[rq] switch is
87
+ recommended instead.
88
+ .RS
89
+ .RE
90
+ .TP
91
+ .B -s, --server SERVER
92
+ No-op, this exists only for compatibility with rackup(1).
93
+ .RS
94
+ .RE
95
+ .SH RUBY OPTIONS
96
+ .TP
97
+ .B -e, --eval LINE
98
+ Evaluate a LINE of Ruby code.
99
+ This evaluation happens immediately as the command-line is being
100
+ parsed.
101
+ .RS
102
+ .RE
103
+ .TP
104
+ .B -d, --debug
105
+ Turn on debug mode, the $DEBUG variable is set to true.
106
+ .RS
107
+ .RE
108
+ .TP
109
+ .B -w, --warn
110
+ Turn on verbose warnings, the $VERBOSE variable is set to true.
111
+ .RS
112
+ .RE
113
+ .TP
114
+ .B -I, --include PATH
115
+ specify $LOAD_PATH.
116
+ PATH will be prepended to $LOAD_PATH.
117
+ The \[aq]:\[aq] character may be used to delimit multiple
118
+ directories.
119
+ This directive may be used more than once.
120
+ Modifications to $LOAD_PATH take place immediately and in the order
121
+ they were specified on the command-line.
122
+ .RS
123
+ .RE
124
+ .TP
125
+ .B -r, --require LIBRARY
126
+ require a specified LIBRARY before executing the application.
127
+ The "require" statement will be executed immediately and in the
128
+ order they were specified on the command-line.
129
+ .RS
130
+ .RE
131
+ .SH SIGNALS
132
+ .PP
133
+ The following UNIX signals may be sent to Zbatery (only supported
134
+ on UNIX):
135
+ .IP \[bu] 2
136
+ HUP - reexecute the binary and exit the current one
137
+ .IP \[bu] 2
138
+ INT/TERM - quick shutdown, quit immediately
139
+ .IP \[bu] 2
140
+ QUIT - graceful shutdown, waits for current requests before exiting
141
+ .IP \[bu] 2
142
+ USR1 - reopen all logs owned by the master and all workers See
143
+ Unicorn::Util.reopen_logs for what is considered a log.
144
+ .IP \[bu] 2
145
+ USR2 - reexecute the running binary.
146
+ A separate QUIT should be sent to the original process once the
147
+ child is verified to be up and running.
148
+ .SH RACK ENVIRONMENT
149
+ .PP
150
+ Accepted values of RACK_ENV and the middleware they automatically
151
+ load (outside of RACKUP_FILE) are exactly as those in rackup(1):
152
+ .IP \[bu] 2
153
+ development - loads Rack::CommonLogger, Rack::ShowExceptions, and
154
+ Rack::Lint middleware
155
+ .IP \[bu] 2
156
+ deployment - loads Rack::CommonLogger middleware
157
+ .IP \[bu] 2
158
+ none - loads no middleware at all, relying entirely on RACKUP_FILE
159
+ .PP
160
+ All unrecognized values for RACK_ENV are assumed to be
161
+ \[lq]none\[rq].
162
+ Production deployments are strongly encouraged to use
163
+ \[lq]deployment\[rq] or \[lq]none\[rq] for maximum performance.
164
+ .PP
165
+ Note that the Rack::ContentLength and Rack::Chunked middlewares are
166
+ never loaded by default.
167
+ If needed, they should be individually specified in the
168
+ RACKUP_FILE, some frameworks do not require them.
169
+ .SH SEE ALSO
170
+ .IP \[bu] 2
171
+ unicorn(1)
172
+ .IP \[bu] 2
173
+ rainbows(1)
174
+ .IP \[bu] 2
175
+ \f[I]Rack::Builder\f[] ri/RDoc
176
+ .IP \[bu] 2
177
+ \f[I]Unicorn::Configurator\f[] ri/RDoc
178
+ .IP \[bu] 2
179
+ Zbatery RDoc (http://zbatery.bogomip.org/)
180
+ .IP \[bu] 2
181
+ Rack RDoc (http://rack.rubyforge.org/doc/)
182
+ .IP \[bu] 2
183
+ Rackup HowTo (http://wiki.github.com/rack/rack/tutorial-rackup-howto)
184
+ .IP \[bu] 2
185
+ Rainbows! RDoc (http://rainbows.rubyforge.org/)
186
+ .SH AUTHOR
187
+ Zbatery hackers <rainbows-talk@rubyforge.org>