passenger 3.0.12 → 3.0.13
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/DEVELOPERS.TXT +1 -0
- data/NEWS +11 -0
- data/bin/passenger-install-nginx-module +1 -1
- data/build/basics.rb +0 -1
- data/build/documentation.rb +17 -8
- data/build/packaging.rb +2 -2
- data/doc/Architectural overview.html +987 -133
- data/doc/Architectural overview.idmap.txt +36 -0
- data/doc/Architectural overview.txt +150 -74
- data/doc/Security of user switching support.html +820 -54
- data/doc/Security of user switching support.idmap.txt +34 -0
- data/doc/Users guide Apache.html +1675 -633
- data/doc/Users guide Apache.idmap.txt +298 -0
- data/doc/Users guide Apache.txt +3 -11
- data/doc/Users guide Nginx.html +1462 -452
- data/doc/Users guide Nginx.idmap.txt +218 -0
- data/doc/Users guide Standalone.html +979 -44
- data/doc/Users guide Standalone.idmap.txt +18 -0
- data/doc/images/many_web_framework_protocols.png +0 -0
- data/doc/images/passenger_architecture.png +0 -0
- data/doc/images/passenger_architecture.svg +198 -215
- data/doc/images/rack.png +0 -0
- data/ext/boost/config/stdlib/libstdcpp3.hpp +2 -1
- data/ext/boost/exception/detail/error_info_impl.hpp +1 -1
- data/ext/common/AgentBase.cpp +15 -5
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedMessageServer.h +1 -1
- data/ext/common/StaticString.h +2 -1
- data/ext/common/Watchdog.cpp +2 -2
- data/ext/libev/config.h +122 -0
- data/ext/nginx/Configuration.c +24 -8
- data/ext/nginx/ContentHandler.c +5 -6
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/abstract_request_handler.rb +11 -8
- data/lib/phusion_passenger/dependencies.rb +12 -18
- data/lib/phusion_passenger/platform_info/compiler.rb +8 -2
- data/lib/phusion_passenger/platform_info/ruby.rb +3 -2
- data/lib/phusion_passenger/rails3_extensions/init.rb +6 -4
- data/lib/phusion_passenger/standalone/command.rb +10 -13
- data/lib/phusion_passenger/standalone/runtime_installer.rb +2 -2
- data/lib/phusion_passenger/standalone/start_command.rb +32 -16
- data/lib/phusion_passenger/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +1 -1
- data/lib/phusion_passenger/templates/standalone/config.erb +2 -1
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
- metadata +21 -16
- data/doc/Users guide Apache with comments.html +0 -4830
- data/lib/phusion_passenger/platform_info/documentation_tools.rb +0 -35
- data/test/stub/rails_apps/3.0/empty/log/development.log +0 -3
@@ -0,0 +1,298 @@
|
|
1
|
+
###### Autogenerated by Mizuho, DO NOT EDIT ######
|
2
|
+
# This file maps section names to IDs so that the commenting system knows which
|
3
|
+
# comments belong to which section. Section names may be changed at will but
|
4
|
+
# IDs always stay the same, allowing one to retain old comments even if you
|
5
|
+
# rename a section.
|
6
|
+
#
|
7
|
+
# This file is autogenerated but is not a cache; you MUST NOT DELETE this
|
8
|
+
# file and you must check it into your version control system. If you lose
|
9
|
+
# this file you may lose the ability to identity old comments.
|
10
|
+
#
|
11
|
+
# Entries marked with "fuzzy" indicate that the section title has changed
|
12
|
+
# and that Mizuho has found an ID which appears to be associated with that
|
13
|
+
# section. You should check whether it is correct, and if not, fix it.
|
14
|
+
|
15
|
+
1. Support information => support-information-zkewk3
|
16
|
+
|
17
|
+
1.1. Supported operating systems => supported-operating-systems-rhbg35
|
18
|
+
|
19
|
+
1.2. Where to get support => where-to-get-support-f3pbrb
|
20
|
+
|
21
|
+
10. Appendix A: About this document => appendix-a-about-this-document-103toqs
|
22
|
+
|
23
|
+
11. Appendix B: Terminology => appendix-b-terminology-h4eaf4
|
24
|
+
|
25
|
+
11.1. Application root => application-root-otx6xf
|
26
|
+
|
27
|
+
12. Appendix C: Spawning methods explained => appendix-c-spawning-methods-explained-owghi9
|
28
|
+
|
29
|
+
12.1. The most straightforward and traditional way: conservative spawning => the-most-straightforward-and-traditional-way-conservative-spawning-1ybbli2
|
30
|
+
|
31
|
+
12.2. The smart spawning method => the-smart-spawning-method-1cvu9dd
|
32
|
+
|
33
|
+
12.2.1. How it works => how-it-works-672zja
|
34
|
+
|
35
|
+
12.2.2. Summary of benefits => summary-of-benefits-1yrihfb
|
36
|
+
|
37
|
+
12.3. Smart spawning gotcha #1: unintentional file descriptor sharing => smart-spawning-gotcha-1-unintentional-file-descriptor-sharing-z1y55l
|
38
|
+
|
39
|
+
12.3.1. Example 1: Memcached connection sharing (harmful) => example-1-memcached-connection-sharing-harmful--c71wqw
|
40
|
+
|
41
|
+
12.3.2. Example 2: Log file sharing (not harmful) => example-2-log-file-sharing-not-harmful--1p2yuol
|
42
|
+
|
43
|
+
12.4. Smart spawning gotcha #2: the need to revive threads => smart-spawning-gotcha-2-the-need-to-revive-threads-1k6cj7d
|
44
|
+
|
45
|
+
12.5. Smart spawning gotcha #3: code load order => smart-spawning-gotcha-3-code-load-order-nkotiy
|
46
|
+
|
47
|
+
2. Installing, upgrading and uninstalling Phusion Passenger => installing-upgrading-and-uninstalling-phusion-passenger-laryvs
|
48
|
+
|
49
|
+
2.1. Generic installation instructions => generic-installation-instructions-17jo43j
|
50
|
+
|
51
|
+
2.1.1. Overview of installation methods => overview-of-installation-methods-12vnjyb
|
52
|
+
|
53
|
+
2.1.2. Preparation (gem and source tarball only) => preparation-gem-and-source-tarball-only--1sxhbgg
|
54
|
+
|
55
|
+
2.1.3. Installing via the gem => installing-via-the-gem-39jw1u
|
56
|
+
|
57
|
+
2.1.4. Installing via the source tarball => installing-via-the-source-tarball-1cgxrqc
|
58
|
+
|
59
|
+
2.1.5. Installing via a native Linux package => installing-via-a-native-linux-package-i1tmhg
|
60
|
+
|
61
|
+
2.1.6. What does the installer do? => what-does-the-installer-do--3a7z1w
|
62
|
+
|
63
|
+
2.2. Operating system-specific instructions and information => operating-system-specific-instructions-and-information-1dfz365
|
64
|
+
|
65
|
+
2.2.1. MacOS X => macos-x-1lcpbz2
|
66
|
+
|
67
|
+
2.2.2. Ubuntu Linux => ubuntu-linux-1xwc66
|
68
|
+
|
69
|
+
2.2.3. OpenSolaris => opensolaris-1e0dynj
|
70
|
+
|
71
|
+
2.3. Upgrading or downgrading Phusion Passenger => upgrading-or-downgrading-phusion-passenger-1dl8km6
|
72
|
+
|
73
|
+
2.3.1. Via a gem or a source tarball => via-a-gem-or-a-source-tarball-1vgkwhs
|
74
|
+
|
75
|
+
2.3.2. Via a native Linux package => via-a-native-linux-package-8dvooa
|
76
|
+
|
77
|
+
2.4. Unloading (disabling) Phusion Passenger from Apache without uninstalling it => unloading-disabling-phusion-passenger-from-apache-without-uninstalling-it-s1axnx
|
78
|
+
|
79
|
+
2.5. Uninstalling Phusion Passenger => uninstalling-phusion-passenger-1qb4ssq
|
80
|
+
|
81
|
+
3. Deploying a Ruby on Rails 1.x or 2.x (but NOT Rails >= 3.x) application => deploying-a-ruby-on-rails-1-x-or-2-x-but-not-rails-3-x-application-9r92hi
|
82
|
+
|
83
|
+
3.1. Deploying to a virtual host’s root => deploying-to-a-virtual-host-s-root-zzo4v7
|
84
|
+
|
85
|
+
3.2. Deploying to a sub URI => deploying-to-a-sub-uri-zekba6
|
86
|
+
|
87
|
+
3.3. Redeploying (restarting the Ruby on Rails application) => redeploying-restarting-the-ruby-on-rails-application--m5zqc6
|
88
|
+
|
89
|
+
3.4. Migrations => migrations-15238b4
|
90
|
+
|
91
|
+
3.5. Capistrano integration => capistrano-integration-1o4cbyq
|
92
|
+
|
93
|
+
4. Deploying a Rack-based Ruby application (including Rails >= 3) => deploying-a-rack-based-ruby-application-including-rails-3--hcs66f
|
94
|
+
|
95
|
+
4.1. Tutorial/example: writing and deploying a Hello World Rack application => tutorial-example-writing-and-deploying-a-hello-world-rack-application-axp5z5
|
96
|
+
|
97
|
+
4.2. Deploying to a virtual host’s root => deploying-to-a-virtual-host-s-root-ab4zj6
|
98
|
+
|
99
|
+
4.3. Deploying to a sub URI => deploying-to-a-sub-uri-13rfygg
|
100
|
+
|
101
|
+
4.4. Redeploying (restarting the Rack application) => redeploying-restarting-the-rack-application--18m41m1
|
102
|
+
|
103
|
+
4.5. Rackup specifications for various web frameworks => rackup-specifications-for-various-web-frameworks-ndsqc2
|
104
|
+
|
105
|
+
4.5.1. Camping => camping-1kxexk0
|
106
|
+
|
107
|
+
4.5.2. Halcyon => halcyon-1ghnpmz
|
108
|
+
|
109
|
+
4.5.3. Mack => mack-miht6b
|
110
|
+
|
111
|
+
4.5.4. Merb => merb-iyj7qy
|
112
|
+
|
113
|
+
4.5.5. Ramaze => ramaze-boddtj
|
114
|
+
|
115
|
+
4.5.6. Sinatra => sinatra-1hubto4
|
116
|
+
|
117
|
+
5. Configuring Phusion Passenger => configuring-phusion-passenger-11oztoe
|
118
|
+
|
119
|
+
5.1. PassengerRoot <directory> => passengerroot-directory--sere8l
|
120
|
+
|
121
|
+
5.10. PassengerBufferResponse <on|off> => passengerbufferresponse-on-off--1y7ilka
|
122
|
+
|
123
|
+
5.11. Security options => security-options-1pb75ho
|
124
|
+
|
125
|
+
5.11.1. PassengerUserSwitching <on|off> => passengeruserswitching-on-off--100dc63
|
126
|
+
|
127
|
+
5.11.2. PassengerUser <username> => passengeruser-username--iw6865
|
128
|
+
|
129
|
+
5.11.3. PassengerGroup <group name> => passengergroup-group-name--1ciwtix
|
130
|
+
|
131
|
+
5.11.4. PassengerDefaultUser <username> => passengerdefaultuser-username--nbjs8w
|
132
|
+
|
133
|
+
5.11.5. PassengerDefaultGroup <group name> => passengerdefaultgroup-group-name--1xwd1xj
|
134
|
+
|
135
|
+
5.11.6. PassengerFriendlyErrorPages <on|off> => passengerfriendlyerrorpages-on-off--rdq45f
|
136
|
+
|
137
|
+
5.12. Resource control and optimization options => resource-control-and-optimization-options-zu2f7u
|
138
|
+
|
139
|
+
5.12.1. PassengerMaxPoolSize <integer> => passengermaxpoolsize-integer--am64q8
|
140
|
+
|
141
|
+
5.12.2. PassengerMinInstances <integer> => passengermininstances-integer--wegq6b
|
142
|
+
|
143
|
+
5.12.3. PassengerMaxInstancesPerApp <integer> => passengermaxinstancesperapp-integer--1pteawn
|
144
|
+
|
145
|
+
5.12.4. PassengerPoolIdleTime <integer> => passengerpoolidletime-integer--a3gunq
|
146
|
+
|
147
|
+
5.12.5. PassengerMaxRequests <integer> => passengermaxrequests-integer--ietgd0
|
148
|
+
|
149
|
+
5.12.6. PassengerStatThrottleRate <integer> => passengerstatthrottlerate-integer--13zx4xo
|
150
|
+
|
151
|
+
5.12.7. PassengerPreStart <url> => passengerprestart-url--1v76tcz
|
152
|
+
|
153
|
+
5.12.8. PassengerHighPerformance <on|off> => passengerhighperformance-on-off--36mw1l
|
154
|
+
|
155
|
+
5.13. Compatibility options => compatibility-options-8jve5a
|
156
|
+
|
157
|
+
5.13.1. PassengerResolveSymlinksInDocumentRoot <on|off> => passengerresolvesymlinksindocumentroot-on-off--vblz7e
|
158
|
+
|
159
|
+
5.13.2. PassengerAllowEncodedSlashes <on|off> => passengerallowencodedslashes-on-off--1ud9a92
|
160
|
+
|
161
|
+
5.14. Logging and debugging options => logging-and-debugging-options-el2cuc
|
162
|
+
|
163
|
+
5.14.1. PassengerLogLevel <integer> => passengerloglevel-integer--1lt2yhq
|
164
|
+
|
165
|
+
5.14.2. PassengerDebugLogFile <filename> => passengerdebuglogfile-filename--pgj55c
|
166
|
+
|
167
|
+
5.15. Ruby on Rails-specific options => ruby-on-rails-specific-options-1t10wfu
|
168
|
+
|
169
|
+
5.15.1. RailsAutoDetect <on|off> => railsautodetect-on-off--tpigsd
|
170
|
+
|
171
|
+
5.15.2. RailsBaseURI <uri> => railsbaseuri-uri--1txrw3k
|
172
|
+
|
173
|
+
5.15.3. RailsEnv <string> => railsenv-string--1b0xxvu
|
174
|
+
|
175
|
+
5.15.4. RailsFrameworkSpawnerIdleTime <integer> => railsframeworkspawneridletime-integer--1ai8dgq
|
176
|
+
|
177
|
+
5.15.5. RailsAppSpawnerIdleTime <integer> => railsappspawneridletime-integer--1awgog1
|
178
|
+
|
179
|
+
5.16. Rack-specific options => rack-specific-options-wk9qzt
|
180
|
+
|
181
|
+
5.16.1. RackAutoDetect <on|off> => rackautodetect-on-off--vl1lxy
|
182
|
+
|
183
|
+
5.16.2. RackBaseURI <uri> => rackbaseuri-uri--1to24pj
|
184
|
+
|
185
|
+
5.16.3. RackEnv <string> => rackenv-string--vve9py
|
186
|
+
|
187
|
+
5.17. Deprecated options => deprecated-options-pm9m57
|
188
|
+
|
189
|
+
5.17.1. RailsRuby => railsruby-ht09ei
|
190
|
+
|
191
|
+
5.17.2. RailsUserSwitching => railsuserswitching-1npx8y4
|
192
|
+
|
193
|
+
5.17.3. RailsDefaultUser => railsdefaultuser-19j7n3m
|
194
|
+
|
195
|
+
5.17.4. RailsAllowModRewrite => railsallowmodrewrite-1vkziro
|
196
|
+
|
197
|
+
5.17.5. RailsSpawnMethod => railsspawnmethod-1aljgpa
|
198
|
+
|
199
|
+
5.2. PassengerRuby <filename> => passengerruby-filename--1r3fv73
|
200
|
+
|
201
|
+
5.3. PassengerAppRoot <path/to/root> => passengerapproot-path-to-root--uf24yd
|
202
|
+
|
203
|
+
5.4. PassengerSpawnMethod <string> => passengerspawnmethod-string--sodg2y
|
204
|
+
|
205
|
+
5.5. PassengerUseGlobalQueue <on|off> => passengeruseglobalqueue-on-off--1ki369
|
206
|
+
|
207
|
+
5.6. PassengerEnabled <on|off> => passengerenabled-on-off--74rzth
|
208
|
+
|
209
|
+
5.7. PassengerTempDir <directory> => passengertempdir-directory--68h2ng
|
210
|
+
|
211
|
+
5.8. PassengerUploadBufferDir <directory> => passengeruploadbufferdir-directory--kdr8at
|
212
|
+
|
213
|
+
5.9. PassengerRestartDir <directory> => passengerrestartdir-directory--1fmhmv0
|
214
|
+
|
215
|
+
6. Troubleshooting => troubleshooting-2ihihi
|
216
|
+
|
217
|
+
6.1. Operating system-specific problems => operating-system-specific-problems-327gbk
|
218
|
+
|
219
|
+
6.1.1. MacOS X: The installer cannot locate MAMP’s Apache => macos-x-the-installer-cannot-locate-mamp-s-apache-or908n
|
220
|
+
|
221
|
+
6.2. Problems during installation => problems-during-installation-q1vlsu
|
222
|
+
|
223
|
+
6.2.1. Ruby development headers aren’t installed => ruby-development-headers-aren-t-installed-1yqrom8
|
224
|
+
|
225
|
+
6.2.2. Apache development headers aren’t installed => apache-development-headers-aren-t-installed-x2473y
|
226
|
+
|
227
|
+
6.2.3. APR development headers aren’t installed => apr-development-headers-aren-t-installed-13bk976
|
228
|
+
|
229
|
+
6.2.4. Phusion Passenger is using the wrong Apache during installation => phusion-passenger-is-using-the-wrong-apache-during-installation-82qnt4
|
230
|
+
|
231
|
+
6.2.5. Phusion Passenger is using the wrong Ruby during installation => phusion-passenger-is-using-the-wrong-ruby-during-installation-1nh3zml
|
232
|
+
|
233
|
+
6.3. Problems after installation => problems-after-installation-fwd23q
|
234
|
+
|
235
|
+
6.3.1. My Rails application works on Mongrel, but not on Phusion Passenger => my-rails-application-works-on-mongrel-but-not-on-phusion-passenger-1f28drx
|
236
|
+
|
237
|
+
6.3.2. Phusion Passenger has been compiled against the wrong Apache installation => phusion-passenger-has-been-compiled-against-the-wrong-apache-installation-n74ce0
|
238
|
+
|
239
|
+
6.3.3. I get a "403 Forbidden" error => i-get-a-403-forbidden-error-m0rlay
|
240
|
+
|
241
|
+
6.3.4. Static assets such as images and stylesheets aren’t being displayed => static-assets-such-as-images-and-stylesheets-aren-t-being-displayed-uaptpi
|
242
|
+
|
243
|
+
6.3.5. The Apache error log says that the spawn manager script does not exist, or that it does not have permission to execute it => the-apache-error-log-says-that-the-spawn-manager-script-does-not-exist-or-that-it-does-not-have-permission-to-execute-it-1fmoozk
|
244
|
+
|
245
|
+
6.3.6. The Rails application reports that it’s unable to start because of a permission error => the-rails-application-reports-that-it-s-unable-to-start-because-of-a-permission-error-v53i6s
|
246
|
+
|
247
|
+
6.3.7. My Rails application’s log file is not being written to => my-rails-application-s-log-file-is-not-being-written-to-3i747l
|
248
|
+
|
249
|
+
6.3.8. I’ve deployed my app on SSL, but the app thinks its not on SSL => i-ve-deployed-my-app-on-ssl-but-the-app-thinks-its-not-on-ssl-10rvgnr
|
250
|
+
|
251
|
+
6.4. Conflicting Apache modules => conflicting-apache-modules-1uwpixk
|
252
|
+
|
253
|
+
6.4.1. mod_userdir => mod-userdir-x5e2te
|
254
|
+
|
255
|
+
6.4.2. MultiViews (mod_negotiation) => multiviews-mod-negotiation--zchfg0
|
256
|
+
|
257
|
+
6.4.3. VirtualDocumentRoot => virtualdocumentroot-14cwd7l
|
258
|
+
|
259
|
+
7. Analysis and system maintenance => analysis-and-system-maintenance-qvkwzr
|
260
|
+
|
261
|
+
7.1. Inspecting memory usage => inspecting-memory-usage-1bkis6i
|
262
|
+
|
263
|
+
7.2. Inspecting Phusion Passenger’s internal status => inspecting-phusion-passenger-s-internal-status-ukekf7
|
264
|
+
|
265
|
+
7.3. Debugging frozen applications => debugging-frozen-applications-1qsjqq7
|
266
|
+
|
267
|
+
7.4. Accessing individual application processes => accessing-individual-application-processes-1p0j4jb
|
268
|
+
|
269
|
+
8. Tips => tips-19cwwf7
|
270
|
+
|
271
|
+
8.1. User switching (security) => user-switching-security--8njx1x
|
272
|
+
|
273
|
+
8.10. Upload progress => upload-progress-71cyl7
|
274
|
+
|
275
|
+
8.2. Reducing memory consumption of Ruby on Rails applications by 33% => reducing-memory-consumption-of-ruby-on-rails-applications-by-33--1ubxnq0
|
276
|
+
|
277
|
+
8.3. Capistrano recipe => capistrano-recipe-syzgo7
|
278
|
+
|
279
|
+
8.4. Bundler support => bundler-support-cf72ih
|
280
|
+
|
281
|
+
8.5. Moving Phusion Passenger to a different directory => moving-phusion-passenger-to-a-different-directory-16fapwo
|
282
|
+
|
283
|
+
8.6. Installing multiple Ruby on Rails versions => installing-multiple-ruby-on-rails-versions-mi5j14
|
284
|
+
|
285
|
+
8.7. Making the application restart after each request => making-the-application-restart-after-each-request-183bezx
|
286
|
+
|
287
|
+
8.8. How to fix broken images/CSS/JavaScript URIs in sub-URI deployments => how-to-fix-broken-images-css-javascript-uris-in-sub-uri-deployments-a63b6r
|
288
|
+
|
289
|
+
8.9. X-Sendfile support => x-sendfile-support-1cgyykw
|
290
|
+
|
291
|
+
9. Under the hood => under-the-hood-21ue5t
|
292
|
+
|
293
|
+
9.1. Static assets serving => static-assets-serving-wo2d9v
|
294
|
+
|
295
|
+
9.2. Page caching support => page-caching-support-kwq9b9
|
296
|
+
|
297
|
+
9.3. How Phusion Passenger detects whether a virtual host is a web application => how-phusion-passenger-detects-whether-a-virtual-host-is-a-web-application-179mp8m
|
298
|
+
|
data/doc/Users guide Apache.txt
CHANGED
@@ -203,15 +203,7 @@ installation. Furthermore, the 'passenger-x.x.x' folder must be accessible by Ap
|
|
203
203
|
|
204
204
|
==== Installing via a native Linux package ====
|
205
205
|
|
206
|
-
John Leach from Brightbox has kindly provided
|
207
|
-
|
208
|
-
Please install the native Linux package, e.g.:
|
209
|
-
------------------------------------------------------
|
210
|
-
sudo sh -c 'echo "deb http://apt.brightbox.net hardy main" > /etc/apt/sources.list.d/brightbox.list'
|
211
|
-
sudo sh -c 'wget -q -O - http://apt.brightbox.net/release.asc | apt-key add -'
|
212
|
-
sudo apt-get update
|
213
|
-
sudo apt-get install libapache2-mod-passenger
|
214
|
-
------------------------------------------------------
|
206
|
+
John Leach from Brightbox has kindly provided a Ubuntu packages for Phusion Passenger. The package is available from the link:http://wiki.brightbox.co.uk/docs:phusion-passenger[Brightbox repository].
|
215
207
|
|
216
208
|
==== What does the installer do? ====
|
217
209
|
|
@@ -635,8 +627,8 @@ For example:
|
|
635
627
|
Allow from all
|
636
628
|
</Directory>
|
637
629
|
|
638
|
-
RackBaseURI /
|
639
|
-
<Directory /websites/phusion/
|
630
|
+
RackBaseURI /rack # <-- These lines have
|
631
|
+
<Directory /websites/phusion/rack> # <-- been added.
|
640
632
|
Options -MultiViews # <--
|
641
633
|
</Directory> # <--
|
642
634
|
</VirtualHost>
|
data/doc/Users guide Nginx.html
CHANGED
@@ -1,20 +1,10 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
5
|
-
<meta name="generator" content="AsciiDoc 8.6.
|
6
|
-
<title>Phusion Passenger users guide, Nginx version</title>
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
5
|
+
<meta name="generator" content="AsciiDoc 8.6.7">
|
6
|
+
<title>Phusion Passenger users guide, Nginx version</title>
|
7
7
|
<style type="text/css">
|
8
|
-
/*
|
9
|
-
* AsciiDoc 'flask' theme for xhtml11 and html5 backends. A shameless knock-off
|
10
|
-
* of the Flask website styling (http://flask.pocoo.org/docs/).
|
11
|
-
*
|
12
|
-
* The implementation is straight-forward, consisting of the asciidoc.css file
|
13
|
-
* followed by theme specific overrides.
|
14
|
-
*
|
15
|
-
* */
|
16
|
-
|
17
|
-
|
18
8
|
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
|
19
9
|
|
20
10
|
/* Default font. */
|
@@ -99,6 +89,7 @@ ul > li > * { color: black; }
|
|
99
89
|
pre {
|
100
90
|
padding: 0;
|
101
91
|
margin: 0;
|
92
|
+
overflow: auto;
|
102
93
|
}
|
103
94
|
|
104
95
|
#author {
|
@@ -525,6 +516,29 @@ th.tableblock.valign-bottom, td.tableblock.valign-bottom {
|
|
525
516
|
}
|
526
517
|
|
527
518
|
|
519
|
+
/*
|
520
|
+
* manpage specific
|
521
|
+
*
|
522
|
+
* */
|
523
|
+
|
524
|
+
body.manpage h1 {
|
525
|
+
padding-top: 0.5em;
|
526
|
+
padding-bottom: 0.5em;
|
527
|
+
border-top: 2px solid silver;
|
528
|
+
border-bottom: 2px solid silver;
|
529
|
+
}
|
530
|
+
body.manpage h2 {
|
531
|
+
border-style: none;
|
532
|
+
}
|
533
|
+
body.manpage div.sectionbody {
|
534
|
+
margin-left: 3em;
|
535
|
+
}
|
536
|
+
|
537
|
+
@media print {
|
538
|
+
body.manpage div#toc { display: none; }
|
539
|
+
}
|
540
|
+
|
541
|
+
|
528
542
|
/*
|
529
543
|
* Theme specific overrides of the preceding (asciidoc.css) CSS.
|
530
544
|
*
|
@@ -551,7 +565,7 @@ h1 { font-size: 240%; }
|
|
551
565
|
h2 { font-size: 180%; }
|
552
566
|
h3 { font-size: 150%; }
|
553
567
|
h4 { font-size: 130%; }
|
554
|
-
h5 { font-size:
|
568
|
+
h5 { font-size: 115%; }
|
555
569
|
h6 { font-size: 100%; }
|
556
570
|
#header h1 { margin-top: 0; }
|
557
571
|
#toc {
|
@@ -589,7 +603,7 @@ div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock
|
|
589
603
|
div.verseblock { border-left-width: 0; margin-left: 3em; }
|
590
604
|
div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
|
591
605
|
div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }
|
592
|
-
</style>
|
606
|
+
</style>
|
593
607
|
<script type="text/javascript">
|
594
608
|
/*<![CDATA[*/
|
595
609
|
var asciidoc = { // Namespace.
|
@@ -633,7 +647,7 @@ toc: function (toclevels) {
|
|
633
647
|
|
634
648
|
function tocEntries(el, toclevels) {
|
635
649
|
var result = new Array;
|
636
|
-
var re = new RegExp('[hH]([
|
650
|
+
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
|
637
651
|
// Function that scans the DOM tree for header elements (the DOM2
|
638
652
|
// nodeIterator API would be a better technique but not supported by all
|
639
653
|
// browsers).
|
@@ -662,7 +676,7 @@ toc: function (toclevels) {
|
|
662
676
|
var i;
|
663
677
|
for (i = 0; i < toc.childNodes.length; i++) {
|
664
678
|
var entry = toc.childNodes[i];
|
665
|
-
if (entry.nodeName == '
|
679
|
+
if (entry.nodeName.toLowerCase() == 'div'
|
666
680
|
&& entry.getAttribute("class")
|
667
681
|
&& entry.getAttribute("class").match(/^toclevel/))
|
668
682
|
tocEntriesToRemove.push(entry);
|
@@ -708,7 +722,7 @@ footnotes: function () {
|
|
708
722
|
var entriesToRemove = [];
|
709
723
|
for (i = 0; i < noteholder.childNodes.length; i++) {
|
710
724
|
var entry = noteholder.childNodes[i];
|
711
|
-
if (entry.nodeName == '
|
725
|
+
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
|
712
726
|
entriesToRemove.push(entry);
|
713
727
|
}
|
714
728
|
for (i = 0; i < entriesToRemove.length; i++) {
|
@@ -783,30 +797,270 @@ install: function(toclevels) {
|
|
783
797
|
}
|
784
798
|
asciidoc.install(3);
|
785
799
|
/*]]>*/
|
786
|
-
</script>
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
800
|
+
</script><style type="text/css">
|
801
|
+
body {
|
802
|
+
margin: 1em 10% 1em 10%;
|
803
|
+
}
|
804
|
+
|
805
|
+
a.image {
|
806
|
+
border: none;
|
807
|
+
}
|
808
|
+
|
809
|
+
.comments {
|
810
|
+
display: block;
|
811
|
+
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAYAAAB6kdqOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB0wAAAdMBc2+PegAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAASjSURBVFiFvZdPaBxVHMc/b/7sbNLdxG13s0sbE1jBxELVbVGEgqmQiiBiDxZqKRWhR0Fqe/BSmoNQSNmrt4ISTyV3byWLHorVU5dYtgVpk4DGhXZ1a7rZmXkeMm99eZn9k1b9wY/3Z2f2fX7f3++9mRFSSnQTQgjAAkTkaO2zmtRaCYTSABBqrIEkS6VS9vTp069lMpmClFL4vt8BCsNwWwsQBAHm7+Y4CAKEEEGtVvtlYWHhbqvVagJ/AE90MCGlVDD2xYsXiydPnvza87wXksnk8NDQUFIPQPW7zfXyMAwJw5BGo/FXs9ncvHfv3tKFCxe+aLfbDyKwQEopFZBdLpdfnp2d/Tafz4+5rhsxghAC1d+h/y5gzH69XvdrtdqDs2fPfuT7/jLQkFIGlhBC5HK5oZmZmW8KhUI+kUgIy7KwLAvbtrFte1vfdHVtnKtg9L7yffv2OcViceLSpUufA88DSSGEcABrfn7+zdHR0UnXdWNv1tXqpY6phGVZnRoy/0MIQT6fdw4ePHgUKAK/AU8sQOzfv/+tdDq9x4xKd1MVU51uSvTzVCrlTU9PTwN7AGEBYmRk5FXXdTvk+gI6kJnGQQG6KQQwMjLiTk1NTQIJBQTgmAWst2rhfiBxC3ab00wAbtRugZjb2LzR3O7d2rh7+s2Ztg1IwajChK2DTSlggpuFrHs34H7BOHELqN0Rl5K4P+4GNQioPt8BUqeoqpd+MGYQvQ7DfrCxKVNAcTCws0B7RdrvhO4HtS1lCkYtbKrT7WB8GihdQf2B3FFIPbEH2cY6iAljjk1l4qB2KKSrMwjMblXqpVpfIF2lXjBxULsB06HigDb1lA2ijgm0WyithmS73faJ3iYdgHq9/tOBAwfe9jyvJ4wam1H1O196QT18+HBzeXl5FQgVkLxz5873k5OTzWw2m+oHE6dMHEw3EGBbuh4/fuyvrKysAS1AOkA4Nzf3w5EjR+6m0+mS/tTvBhMH1U2lXgqtra21l5aWvgNWgCYQ2tH/hY1G48epqal3Pc/b4ziOGLQegiCIPVv0ubhDcXV1dfP27dv3y+Xyl0AVqAO+/pKfmpiYeHFubm4+m82+kkgkPNd1nbjI9TaZTNqu61rRQpbrujiOs+O6MAx59OhRuL6+3mq1Wq1KpXJjYWFhMYK5DzSljF7yo7RYwBCQBfKlUml6bGxsMggCLwgC/Ruts4CRPpFMJodnZmbeKBaLLxUKheFMJmPr6a5Wq0+uXLmyWK1WK8DPwBrwO7AhpQxB+y6LoARbhe4Bw0AyGlv0N/Vd56VSqb3nzp378PDhw+/ncrnnCoWCZ1kWvu9z69at9fPnz3+6sbFxE/gVaEkNYhuQBqUvsBtTSnrAKDB25syZ944dO/ZxNpvNjY+PDzebTb9Sqdy8fPnyZ0AN+FOpEwv0rKYFZEdgaSB7/PjxoydOnPgkl8tNAN7169fLi4uLX7G1w/5RadDnz9N4pJbNVupzwHSpVPrg6tWrN65du/broUOHZoEMYHXu+S+BYsA8YC9QHB8ff/3UqVPvREC2uvZfT1kvi9KpNo7LVo1uApsqZf8rkAHWMX2X/Q1tcUY1hl3QyQAAAABJRU5ErkJggg==') top left no-repeat;
|
812
|
+
float: left;
|
813
|
+
margin-left: -55px;
|
814
|
+
width: 36px;
|
815
|
+
height: 48px;
|
816
|
+
line-height: 0;
|
817
|
+
color: black;
|
818
|
+
text-decoration: none !important;
|
819
|
+
border: none !important;
|
820
|
+
}
|
821
|
+
|
822
|
+
#toc .comments {
|
823
|
+
margin-top: 0.25em;
|
824
|
+
}
|
825
|
+
|
826
|
+
.sect1 .comments {
|
827
|
+
margin-top: 0.5em;
|
828
|
+
}
|
829
|
+
|
830
|
+
.sect2 .comments {
|
831
|
+
margin-top: 1.15em;
|
832
|
+
}
|
833
|
+
|
834
|
+
.sect3 .comments {
|
835
|
+
margin-top: -1em;
|
836
|
+
}
|
837
|
+
|
838
|
+
.comments.empty {
|
839
|
+
opacity: 0.2;
|
840
|
+
}
|
841
|
+
|
842
|
+
.comments.empty:hover,
|
843
|
+
.comments.nonempty {
|
844
|
+
opacity: 1;
|
845
|
+
}
|
846
|
+
|
847
|
+
.comments .count {
|
848
|
+
display: block;
|
849
|
+
font-size: 80%;
|
850
|
+
padding-top: 12px;
|
851
|
+
text-align: center;
|
852
|
+
text-shadow: 1px 1px 2px white;
|
853
|
+
}
|
854
|
+
|
855
|
+
#comments_lightbox_shadow {
|
856
|
+
position: fixed;
|
857
|
+
top: 0;
|
858
|
+
left: 0;
|
859
|
+
right: 0;
|
860
|
+
bottom: 0;
|
861
|
+
background: black;
|
862
|
+
opacity: 0.7;
|
863
|
+
z-index: 10;
|
864
|
+
}
|
865
|
+
|
866
|
+
#comments_lightbox_contents {
|
867
|
+
position: fixed;
|
868
|
+
top: 10%;
|
869
|
+
left: 20%;
|
870
|
+
right: 20%;
|
871
|
+
bottom: 10%;
|
872
|
+
background: white;
|
873
|
+
overflow: auto;
|
874
|
+
z-index: 11;
|
875
|
+
}
|
876
|
+
|
877
|
+
#comments_lightbox_contents > .shell {
|
878
|
+
margin: 2em;
|
879
|
+
}
|
880
|
+
|
881
|
+
@media print {
|
882
|
+
body {
|
883
|
+
font-size: 18pt;
|
884
|
+
}
|
885
|
+
|
886
|
+
#header h1 {
|
887
|
+
page-break-after: always;
|
888
|
+
font-size: 500%;
|
889
|
+
vertical-align: middle;
|
890
|
+
}
|
891
|
+
|
892
|
+
#header {
|
893
|
+
page-break-after: always;
|
894
|
+
}
|
895
|
+
|
896
|
+
#toctitle {
|
897
|
+
font-size: 200%;
|
898
|
+
margin-bottom: 1em;
|
899
|
+
}
|
900
|
+
|
901
|
+
div.toclevel1 {
|
902
|
+
font-size: 100%;
|
903
|
+
}
|
904
|
+
|
905
|
+
div.toclevel2 {
|
906
|
+
font-size: 90%;
|
907
|
+
}
|
908
|
+
|
909
|
+
div.toclevel3 {
|
910
|
+
font-size: 80%;
|
911
|
+
}
|
912
|
+
|
913
|
+
#content .comments {
|
914
|
+
display: none;
|
915
|
+
}
|
916
|
+
|
917
|
+
@page :left {
|
918
|
+
@bottom-left {
|
919
|
+
content: counter(page);
|
920
|
+
}
|
921
|
+
}
|
922
|
+
}
|
923
|
+
|
924
|
+
#topbar {
|
925
|
+
position: fixed;
|
926
|
+
left: 0;
|
927
|
+
top: 0;
|
928
|
+
right: 0;
|
929
|
+
height: 2.5em;
|
930
|
+
padding-left: 10%;
|
931
|
+
padding-right: 10%;
|
932
|
+
z-index: 1;
|
933
|
+
background: #880000;
|
934
|
+
overflow: hidden;
|
935
|
+
white-space: nowrap;
|
936
|
+
box-shadow: 0px 3px 6px #555555;
|
937
|
+
-moz-box-shadow: 0px 3px 6px #555555;
|
938
|
+
-webkit-box-shadow: 0px 3px 6px #555555;
|
939
|
+
-o-box-shadow: 0px 3px 6px #555555;
|
940
|
+
}
|
941
|
+
|
942
|
+
#topbar .title {
|
943
|
+
display: inline-block;
|
944
|
+
margin: 0.6em 1em 0 0;
|
945
|
+
vertical-align: top;
|
946
|
+
}
|
947
|
+
|
948
|
+
#topbar .title img {
|
949
|
+
display: none;
|
950
|
+
margin-right: 6px;
|
951
|
+
vertical-align: middle;
|
952
|
+
}
|
953
|
+
|
954
|
+
#topbar .title a {
|
955
|
+
color: #fffafa;
|
956
|
+
border: 0;
|
957
|
+
}
|
958
|
+
|
959
|
+
#topbar .title:hover img,
|
960
|
+
.mobile #topbar .title img {
|
961
|
+
display: inline-block;
|
962
|
+
margin-left: -17px;
|
963
|
+
}
|
964
|
+
|
965
|
+
#topbar .title:hover a,
|
966
|
+
.mobile #topbar .title a {
|
967
|
+
color: #ffffdd;
|
968
|
+
}
|
969
|
+
|
970
|
+
#floattoc {
|
971
|
+
position: fixed;
|
972
|
+
z-index: 1;
|
973
|
+
top: 2em;
|
974
|
+
bottom: 20%;
|
975
|
+
width: 50%;
|
976
|
+
background: #f0f0f0;
|
977
|
+
color: black;
|
978
|
+
box-shadow: 0px 6px 6px #555555;
|
979
|
+
-moz-box-shadow: 0px 6px 6px #555555;
|
980
|
+
-webkit-box-shadow: 0px 6px 6px #555555;
|
981
|
+
-o-box-shadow: 0px 6px 6px #555555;
|
982
|
+
overflow: auto;
|
983
|
+
padding: 1em;
|
984
|
+
border-radius: 6px;
|
985
|
+
-webkit-border-radius: 8px;
|
986
|
+
-webkit-border-top-left-radius: 0;
|
987
|
+
-webkit-border-top-right-radius: 0;
|
988
|
+
-moz-border-radius: 8px;
|
989
|
+
-moz-border-radius-topleft: 0;
|
990
|
+
-moz-border-top-right-radius: 0;
|
991
|
+
-o-border-radius: 8px;
|
992
|
+
-o-border-radius-topleft: 0;
|
993
|
+
-o-border-top-right-radius: 0;
|
994
|
+
border-radius: 8px;
|
995
|
+
border-top-left-radius: 0;
|
996
|
+
border-top-right-radius: 0;
|
997
|
+
}
|
998
|
+
|
999
|
+
#floattoc a.current {
|
1000
|
+
font-weight: bold;
|
1001
|
+
color: black;
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
#current_section {
|
1005
|
+
display: inline-block;
|
1006
|
+
margin: 0.5em 0 0 0;
|
1007
|
+
padding: 0.2em 0.5em 0.2em 0.5em;
|
1008
|
+
background: #550000;
|
1009
|
+
font-size: 90%;
|
1010
|
+
vertical-align: top;
|
1011
|
+
color: white;
|
1012
|
+
border: none;
|
1013
|
+
-webkit-border-radius: 8px;
|
1014
|
+
-moz-border-radius: 8px;
|
1015
|
+
-o-border-radius: 8px;
|
1016
|
+
border-radius: 8px;
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
#current_section:hover {
|
1020
|
+
text-decoration: none;
|
1021
|
+
border: none;
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
#current_section.pressed {
|
1025
|
+
background: #f0f0f0;
|
1026
|
+
color: black;
|
1027
|
+
-webkit-border-top-left-radius: 8px;
|
1028
|
+
-webkit-border-top-right-radius: 8px;
|
1029
|
+
-webkit-border-bottom-left-radius: 0;
|
1030
|
+
-webkit-border-bottom-right-radius: 0;
|
1031
|
+
-moz-border-radius-topleft: 8px;
|
1032
|
+
-moz-border-radius-topright: 8px;
|
1033
|
+
-moz-border-bottom-left-radius: 0;
|
1034
|
+
-moz-border-bottom-right-radius: 0;
|
1035
|
+
border-top-left-radius: 8px;
|
1036
|
+
border-top-right-radius: 8px;
|
1037
|
+
border-bottom-left-radius: 0;
|
1038
|
+
border-bottom-right-radius: 0;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
</style>
|
1042
|
+
</head>
|
1043
|
+
<body class="article">
|
1044
|
+
<div id="topbar" style="display: none">
|
1045
|
+
<div class="title">
|
1046
|
+
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt=""><a href="javascript:void(Mizuho.smoothlyScrollToToc())">Phusion Passenger users guide, Nginx version</a>
|
1047
|
+
</div>
|
1048
|
+
<a href="javascript:void(0)" id="current_section"></a>
|
795
1049
|
</div>
|
796
|
-
<div id="
|
1050
|
+
<div id="header">
|
1051
|
+
<h1>Phusion Passenger users guide, Nginx version</h1>
|
797
1052
|
<div id="preamble">
|
798
1053
|
<div class="sectionbody">
|
799
1054
|
<div class="paragraph"><p><span class="image">
|
800
1055
|
<a class="image" href="http://www.phusion.nl/">
|
801
|
-
<img src="images/phusion_banner.png" alt="images/phusion_banner.png">
|
802
|
-
</a>
|
1056
|
+
<img src="images/phusion_banner.png" alt="images/phusion_banner.png"></a>
|
803
1057
|
</span></p></div>
|
804
1058
|
<div class="paragraph"><p>Phusion Passenger is an Nginx module, which makes deploying Ruby and Ruby on
|
805
1059
|
Rails applications on Nginx a breeze. It follows the usual Ruby on Rails
|
806
|
-
conventions, such as "Don
|
1060
|
+
conventions, such as "Don’t-Repeat-Yourself" and ease of setup, while at the
|
807
1061
|
same time providing enough flexibility.</p></div>
|
808
1062
|
<div class="paragraph"><p>This users guide will teach you:</p></div>
|
809
|
-
<div class="ulist"><ul>
|
1063
|
+
<div class="ulist"><ul>
|
810
1064
|
<li>
|
811
1065
|
<p>
|
812
1066
|
How to install Nginx with Phusion Passenger support.
|
@@ -837,11 +1091,18 @@ How to solve common problems.
|
|
837
1091
|
using the commandline.</p></div>
|
838
1092
|
</div>
|
839
1093
|
</div>
|
1094
|
+
<div id="toc">
|
1095
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><div id="toctitle">Table of Contents</div>
|
1096
|
+
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
|
1097
|
+
</div>
|
1098
|
+
</div>
|
1099
|
+
<div id="content">
|
1100
|
+
|
840
1101
|
<div class="sect1">
|
841
|
-
<h2 id="_support_information">1. Support information</h2>
|
1102
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_support_information" data-comment-topic="support-information-nl5gdn">1. Support information</h2>
|
842
1103
|
<div class="sectionbody">
|
843
1104
|
<div class="sect2">
|
844
|
-
<h3 id="_supported_operating_systems">1.1. Supported operating systems</h3>
|
1105
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_supported_operating_systems" data-comment-topic="supported-operating-systems-a5n2x4">1.1. Supported operating systems</h3>
|
845
1106
|
<div class="paragraph"><p>Phusion Passenger works on any POSIX-compliant operating system. In other
|
846
1107
|
words: practically any operating system on earth, except Microsoft Windows.</p></div>
|
847
1108
|
<div class="paragraph"><p>Phusion Passenger is confirmed on a large number of operating systems and Linux
|
@@ -851,11 +1112,11 @@ Please
|
|
851
1112
|
<a href="http://code.google.com/p/phusion-passenger/issues/list">report a bug</a>
|
852
1113
|
or
|
853
1114
|
<a href="http://groups.google.com/group/phusion-passenger">join our discussion forum</a>
|
854
|
-
if it doesn
|
1115
|
+
if it doesn’t work on your POSIX-compliant operating system.</p></div>
|
855
1116
|
</div>
|
856
1117
|
<div class="sect2">
|
857
|
-
<h3 id="_where_to_get_support">1.2. Where to get support</h3>
|
858
|
-
<div class="ulist"><ul>
|
1118
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_where_to_get_support" data-comment-topic="where-to-get-support-2s9na5">1.2. Where to get support</h3>
|
1119
|
+
<div class="ulist"><ul>
|
859
1120
|
<li>
|
860
1121
|
<p>
|
861
1122
|
<a href="http://code.google.com/p/phusion-passenger/issues/list">Issue tracker</a> - report
|
@@ -865,7 +1126,7 @@ if it doesn’t work on your POSIX-compliant operating system.</p></div>
|
|
865
1126
|
<li>
|
866
1127
|
<p>
|
867
1128
|
<a href="http://groups.google.com/group/phusion-passenger">Discussion forum</a> - post a
|
868
|
-
message here if you
|
1129
|
+
message here if you’re experiencing problems.
|
869
1130
|
</p>
|
870
1131
|
</li>
|
871
1132
|
</ul></div>
|
@@ -873,15 +1134,15 @@ if it doesn’t work on your POSIX-compliant operating system.</p></div>
|
|
873
1134
|
</div>
|
874
1135
|
</div>
|
875
1136
|
<div class="sect1">
|
876
|
-
<h2 id="_installing_phusion_passenger">2. Installing Phusion Passenger</h2>
|
1137
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_installing_phusion_passenger" data-comment-topic="installing-phusion-passenger-hn03ac">2. Installing Phusion Passenger</h2>
|
877
1138
|
<div class="sectionbody">
|
878
1139
|
<div class="sect2">
|
879
|
-
<h3 id="_overview">2.1. Overview</h3>
|
1140
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_overview" data-comment-topic="overview-kvhzi4">2.1. Overview</h3>
|
880
1141
|
<div class="paragraph"><p>As you might already know, Nginx does not support loadable modules, in contrast
|
881
1142
|
to most other web servers (e.g. Apache). Therefore, to install Phusion Passenger
|
882
1143
|
for Nginx, one must recompile and reinstall Nginx with Phusion Passenger support.
|
883
1144
|
There are two ways to do this:</p></div>
|
884
|
-
<div class="olist arabic"><ol class="arabic">
|
1145
|
+
<div class="olist arabic"><ol class="arabic">
|
885
1146
|
<li>
|
886
1147
|
<p>
|
887
1148
|
By running the Phusion Passenger installer for Nginx. This installer will
|
@@ -894,36 +1155,36 @@ By running the Phusion Passenger installer for Nginx. This installer will
|
|
894
1155
|
<li>
|
895
1156
|
<p>
|
896
1157
|
By manually configuring and compiling Nginx with Phusion Passenger support,
|
897
|
-
through Nginx
|
898
|
-
installer is easier, so you should only use this method if you
|
1158
|
+
through Nginx’s <span class="monospaced">--add-module</span> configure option. Generally, using our
|
1159
|
+
installer is easier, so you should only use this method if you’re already
|
899
1160
|
familiar with compiling Nginx.
|
900
1161
|
</p>
|
901
1162
|
</li>
|
902
1163
|
</ol></div>
|
903
1164
|
<div class="admonitionblock">
|
904
|
-
<table><tr>
|
1165
|
+
<table><tr>
|
905
1166
|
<td class="icon">
|
906
|
-
<img src="./images/icons/tip.png" alt="Tip">
|
1167
|
+
<img src="./images/icons/tip.png" alt="Tip">
|
907
1168
|
</td>
|
908
1169
|
<td class="content">You might have to run the installation commands in the following sections
|
909
1170
|
as <em>root</em>. If the installer fails because of permission errors, it will tell
|
910
1171
|
you.</td>
|
911
|
-
</tr></table>
|
1172
|
+
</tr></table>
|
912
1173
|
</div>
|
913
1174
|
</div>
|
914
1175
|
<div class="sect2">
|
915
|
-
<h3 id="specifying_ruby_installation">2.2. Specifying the correct Ruby installation</h3>
|
916
|
-
<div class="paragraph"><p>If your system has multiple Ruby installations
|
917
|
-
MacOS X, or if you
|
918
|
-
<a href="http://www.rubyenterpriseedition.com">Ruby Enterprise Edition</a
|
1176
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="specifying_ruby_installation" data-comment-topic="specifying-the-correct-ruby-installation-jvqdv6">2.2. Specifying the correct Ruby installation</h3>
|
1177
|
+
<div class="paragraph"><p>If your system has multiple Ruby installations — which is likely the case on
|
1178
|
+
MacOS X, or if you’ve also installed
|
1179
|
+
<a href="http://www.rubyenterpriseedition.com">Ruby Enterprise Edition</a> — then you
|
919
1180
|
will need to tell the operating system which Ruby installation to use, prior to
|
920
1181
|
running the Phusion Passenger installer. If you only have one Ruby installation
|
921
1182
|
(the case on most Linux systems), then you can skip this section because Phusion
|
922
1183
|
Passenger will automatically detect it.</p></div>
|
923
|
-
<div class="paragraph"><p>To specify a Ruby installation, prepend your Ruby installation
|
1184
|
+
<div class="paragraph"><p>To specify a Ruby installation, prepend your Ruby installation’s <span class="monospaced">bin</span>
|
924
1185
|
directory to the <span class="monospaced">PATH</span> environment variable. For example, if you have the
|
925
1186
|
following Ruby installations:</p></div>
|
926
|
-
<div class="ulist"><ul>
|
1187
|
+
<div class="ulist"><ul>
|
927
1188
|
<li>
|
928
1189
|
<p>
|
929
1190
|
/usr/bin/ruby
|
@@ -939,12 +1200,13 @@ following Ruby installations:</p></div>
|
|
939
1200
|
<div class="listingblock">
|
940
1201
|
<div class="content monospaced">
|
941
1202
|
<pre>export PATH=/opt/myruby/bin:$PATH</pre>
|
942
|
-
</div
|
1203
|
+
</div>
|
1204
|
+
</div>
|
943
1205
|
</div>
|
944
1206
|
<div class="sect2">
|
945
|
-
<h3 id="_installing_phusion_passenger_for_nginx_through_the_installer">2.3. Installing Phusion Passenger for Nginx through the installer</h3>
|
1207
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_installing_phusion_passenger_for_nginx_through_the_installer" data-comment-topic="installing-phusion-passenger-for-nginx-through-the-installer-1lqxes1">2.3. Installing Phusion Passenger for Nginx through the installer</h3>
|
946
1208
|
<div class="sect3">
|
947
|
-
<h4 id="_obtaining_the_phusion_passenger_files_and_running_the_installer">2.3.1. Obtaining the Phusion Passenger files and running the installer</h4>
|
1209
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_obtaining_the_phusion_passenger_files_and_running_the_installer" data-comment-topic="obtaining-the-phusion-passenger-files-and-running-the-installer-6l6ula">2.3.1. Obtaining the Phusion Passenger files and running the installer</h4>
|
948
1210
|
<div class="paragraph"><p>You must obtain the Phusion Passenger files in order to run the installer.
|
949
1211
|
This can be done either by installing the Phusion Passenger gem, or by
|
950
1212
|
downloading the source tarball.</p></div>
|
@@ -954,12 +1216,14 @@ downloading the source tarball.</p></div>
|
|
954
1216
|
<div class="listingblock">
|
955
1217
|
<div class="content monospaced">
|
956
1218
|
<pre>gem install passenger</pre>
|
957
|
-
</div
|
1219
|
+
</div>
|
1220
|
+
</div>
|
958
1221
|
<div class="paragraph"><p>Next, run the Phusion Passenger installer for Nginx:</p></div>
|
959
1222
|
<div class="listingblock">
|
960
1223
|
<div class="content monospaced">
|
961
1224
|
<pre>passenger-install-nginx-module</pre>
|
962
|
-
</div
|
1225
|
+
</div>
|
1226
|
+
</div>
|
963
1227
|
<div class="paragraph"><p>Please follow the instructions given by the installer.</p></div>
|
964
1228
|
</div>
|
965
1229
|
<div class="sect4">
|
@@ -973,26 +1237,28 @@ reside in <span class="monospaced">/opt/passenger-x.x.x</span>, then type:</p></
|
|
973
1237
|
<div class="content monospaced">
|
974
1238
|
<pre>cd /opt
|
975
1239
|
tar xzvf ~/YourDownloadsFolder/passenger-x.x.x.tar.gz</pre>
|
976
|
-
</div
|
1240
|
+
</div>
|
1241
|
+
</div>
|
977
1242
|
<div class="paragraph"><p>Next, run the Phusion Passenger installer for Nginx:</p></div>
|
978
1243
|
<div class="listingblock">
|
979
1244
|
<div class="content monospaced">
|
980
1245
|
<pre>/opt/passenger-x.x.x/bin/passenger-install-nginx-module</pre>
|
981
|
-
</div
|
1246
|
+
</div>
|
1247
|
+
</div>
|
982
1248
|
<div class="paragraph"><p>Please follow the instructions given by the installer.</p></div>
|
983
1249
|
<div class="admonitionblock">
|
984
|
-
<table><tr>
|
1250
|
+
<table><tr>
|
985
1251
|
<td class="icon">
|
986
|
-
<img src="./images/icons/important.png" alt="Important">
|
1252
|
+
<img src="./images/icons/important.png" alt="Important">
|
987
1253
|
</td>
|
988
1254
|
<td class="content">Please do not remove the passenger-x.x.x folder after installation.
|
989
1255
|
Furthermore, the passenger-x.x.x folder must be accessible by Nginx.</td>
|
990
|
-
</tr></table>
|
1256
|
+
</tr></table>
|
991
1257
|
</div>
|
992
1258
|
</div>
|
993
1259
|
</div>
|
994
1260
|
<div class="sect3">
|
995
|
-
<h4 id="_non_interactive_automatic_installation">2.3.2. Non-interactive/automatic installation</h4>
|
1261
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_non_interactive_automatic_installation" data-comment-topic="non-interactive-automatic-installation-1u97717">2.3.2. Non-interactive/automatic installation</h4>
|
996
1262
|
<div class="paragraph"><p>By default, the installer is interactive. If you want to automate installation,
|
997
1263
|
then you can do so by passing various answers to the installer through command
|
998
1264
|
line options.</p></div>
|
@@ -1001,32 +1267,34 @@ options.</p></div>
|
|
1001
1267
|
</div>
|
1002
1268
|
</div>
|
1003
1269
|
<div class="sect2">
|
1004
|
-
<h3 id="_installing_phusion_passenger_for_nginx_manually">2.4. Installing Phusion Passenger for Nginx manually</h3>
|
1270
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_installing_phusion_passenger_for_nginx_manually" data-comment-topic="installing-phusion-passenger-for-nginx-manually-1qg1e2x">2.4. Installing Phusion Passenger for Nginx manually</h3>
|
1005
1271
|
<div class="paragraph"><p>You can also install Phusion Passenger the way you install any other Nginx module.
|
1006
|
-
To do this, run Nginx
|
1272
|
+
To do this, run Nginx’s configure script with <span class="monospaced">--add-module=/path-to-passenger-root/ext/nginx</span>.</p></div>
|
1007
1273
|
<div class="paragraph"><p>If you installed Phusion Passenger via the gem, then <em>path-to-passenger-root</em>
|
1008
1274
|
can be obtained with the command:</p></div>
|
1009
1275
|
<div class="listingblock">
|
1010
1276
|
<div class="content monospaced">
|
1011
1277
|
<pre>passenger-config --root</pre>
|
1012
|
-
</div
|
1278
|
+
</div>
|
1279
|
+
</div>
|
1013
1280
|
<div class="paragraph"><p>This will probably output something along the lines of <em>/usr/lib/ruby/gems/1.8/gems/passenger-x.x.x</em>,
|
1014
|
-
so you
|
1281
|
+
so you’ll probably have to specify something like <span class="monospaced">--add-module=/usr/lib/ruby/gems/1.8/gems/passenger-x.x.x/ext/nginx</span>.</p></div>
|
1015
1282
|
<div class="paragraph"><p>If you installed Phusion Passenger via a source tarball, then <em>path-to-passenger-root</em>
|
1016
1283
|
is the directory which contains the Phusion Passenger source code. So if you
|
1017
|
-
extracted the Phusion Passenger source code to <em>/opt/passenger-x.x.x</em>, then you
|
1284
|
+
extracted the Phusion Passenger source code to <em>/opt/passenger-x.x.x</em>, then you’ll
|
1018
1285
|
have to specify <span class="monospaced">--add-module=/opt/passenger-x.x.x/ext/nginx</span>.</p></div>
|
1019
1286
|
<div class="paragraph"><p>After having installed Nginx with Phusion Passenger support, you must paste the following
|
1020
1287
|
line into your Nginx configuration file:</p></div>
|
1021
1288
|
<div class="listingblock">
|
1022
1289
|
<div class="content monospaced">
|
1023
1290
|
<pre>passenger_root /path-to-passenger-root;</pre>
|
1024
|
-
</div
|
1291
|
+
</div>
|
1292
|
+
</div>
|
1025
1293
|
<div class="paragraph"><p>After having done so, restart Nginx.</p></div>
|
1026
1294
|
</div>
|
1027
1295
|
<div class="sect2">
|
1028
|
-
<h3 id="_upgrading_or_downgrading_phusion_passenger_or_nginx_itself">2.5. Upgrading or downgrading Phusion Passenger or Nginx itself</h3>
|
1029
|
-
<div class="paragraph"><p>Whether you
|
1296
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_upgrading_or_downgrading_phusion_passenger_or_nginx_itself" data-comment-topic="upgrading-or-downgrading-phusion-passenger-or-nginx-itself-8dulxz">2.5. Upgrading or downgrading Phusion Passenger or Nginx itself</h3>
|
1297
|
+
<div class="paragraph"><p>Whether you’re upgrading/downgrading Phusion Passenger or Nginx itself (or perhaps both),
|
1030
1298
|
Nginx will have to be recompiled and reinstalled. The procedure is exactly the same as
|
1031
1299
|
a normal installation so just follow the instructions in section 2.3 or 2.4.</p></div>
|
1032
1300
|
<div class="paragraph"><p>When following the installation instructions, eventually <span class="monospaced">passenger-install-nginx-module</span>
|
@@ -1036,26 +1304,27 @@ configuration file; something that looks along the lines of:</p></div>
|
|
1036
1304
|
<div class="content monospaced">
|
1037
1305
|
<pre>passenger_root ...;
|
1038
1306
|
passenger_ruby ...;</pre>
|
1039
|
-
</div
|
1307
|
+
</div>
|
1308
|
+
</div>
|
1040
1309
|
<div class="paragraph"><p>Because you already had Phusion Passenger installed, you already had similar settings
|
1041
1310
|
in your Nginx configuration file, just with different values. <strong>Replace</strong> the old settings with
|
1042
1311
|
the new ones that you are instructed to paste. It is important that the old settings are
|
1043
1312
|
removed, otherwise Phusion Passenger may malfunction.</p></div>
|
1044
|
-
<div class="paragraph"><p>When you
|
1313
|
+
<div class="paragraph"><p>When you’re done, restart Nginx.</p></div>
|
1045
1314
|
</div>
|
1046
1315
|
<div class="sect2">
|
1047
|
-
<h3 id="_unloading_disabling_phusion_passenger_from_nginx_without_uninstalling_it">2.6. Unloading (disabling) Phusion Passenger from Nginx without uninstalling it</h3>
|
1316
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_unloading_disabling_phusion_passenger_from_nginx_without_uninstalling_it" data-comment-topic="unloading-disabling-phusion-passenger-from-nginx-without-uninstalling-it-v447e0">2.6. Unloading (disabling) Phusion Passenger from Nginx without uninstalling it</h3>
|
1048
1317
|
<div class="paragraph"><p>You can temporarily unload (disable) Phusion Passenger from Nginx, without
|
1049
1318
|
uninstalling the Phusion Passenger files, so that Nginx behaves as if Phusion
|
1050
1319
|
Passenger was never installed in the first place. This might be useful to you if,
|
1051
1320
|
for example, you seem to be experiencing a problem caused by Phusion Passenger,
|
1052
|
-
but you want to make sure whether that
|
1321
|
+
but you want to make sure whether that’s actually the case, without having
|
1053
1322
|
to go through the hassle of uninstalling Phusion Passenger completely. When disabled,
|
1054
1323
|
Phusion Passenger will not occupy any memory or CPU or otherwise interfere with
|
1055
1324
|
Nginx.</p></div>
|
1056
1325
|
<div class="paragraph"><p>To unload Phusion Passenger, edit your Nginx configuration file(s)
|
1057
1326
|
and comment out all Phusion Passenger configuration directives.</p></div>
|
1058
|
-
<div class="paragraph"><p>For example, if your configuration file looks like this
|
1327
|
+
<div class="paragraph"><p>For example, if your configuration file looks like this…</p></div>
|
1059
1328
|
<div class="listingblock">
|
1060
1329
|
<div class="content monospaced">
|
1061
1330
|
<pre>...
|
@@ -1075,8 +1344,9 @@ http {
|
|
1075
1344
|
passenger_use_global_queue on;
|
1076
1345
|
}
|
1077
1346
|
}</pre>
|
1078
|
-
</div
|
1079
|
-
|
1347
|
+
</div>
|
1348
|
+
</div>
|
1349
|
+
<div class="paragraph"><p>…then comment out the relevant directives, so that it looks like this:</p></div>
|
1080
1350
|
<div class="listingblock">
|
1081
1351
|
<div class="content monospaced">
|
1082
1352
|
<pre>...
|
@@ -1096,15 +1366,16 @@ http {
|
|
1096
1366
|
# passenger_use_global_queue on;
|
1097
1367
|
}
|
1098
1368
|
}</pre>
|
1099
|
-
</div
|
1100
|
-
|
1369
|
+
</div>
|
1370
|
+
</div>
|
1371
|
+
<div class="paragraph"><p>After you’ve done this, save the file and restart Nginx.</p></div>
|
1101
1372
|
</div>
|
1102
1373
|
<div class="sect2">
|
1103
|
-
<h3 id="_uninstalling_phusion_passenger">2.7. Uninstalling Phusion Passenger</h3>
|
1374
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_uninstalling_phusion_passenger" data-comment-topic="uninstalling-phusion-passenger-wuycvb">2.7. Uninstalling Phusion Passenger</h3>
|
1104
1375
|
<div class="paragraph"><p>To uninstall Phusion Passenger, please first remove all Phusion Passenger
|
1105
|
-
configuration directives from your Nginx configuration file(s). After you
|
1376
|
+
configuration directives from your Nginx configuration file(s). After you’ve
|
1106
1377
|
done this, you need to remove the Phusion Passenger files.</p></div>
|
1107
|
-
<div class="ulist"><ul>
|
1378
|
+
<div class="ulist"><ul>
|
1108
1379
|
<li>
|
1109
1380
|
<p>
|
1110
1381
|
If you installed Phusion Passenger via a gem, then type <span class="monospaced">gem uninstall passenger</span>.
|
@@ -1126,27 +1397,27 @@ Nginx binary.</p></div>
|
|
1126
1397
|
</div>
|
1127
1398
|
</div>
|
1128
1399
|
<div class="sect1">
|
1129
|
-
<h2 id="deploying_a_ror_app">3. Deploying a Ruby on Rails 1.x or 2.x (but NOT Rails >= 3) application</h2>
|
1400
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="deploying_a_ror_app" data-comment-topic="deploying-a-ruby-on-rails-1-x-or-2-x-but-not-rails-3-application-b69gqa">3. Deploying a Ruby on Rails 1.x or 2.x (but NOT Rails >= 3) application</h2>
|
1130
1401
|
<div class="sectionbody">
|
1131
1402
|
<div class="paragraph"><p>Suppose you have a Ruby on Rails application in <em>/webapps/mycook</em>, and you own
|
1132
1403
|
the domain <em>www.mycook.com</em>. You can either deploy your application to the
|
1133
|
-
virtual host
|
1404
|
+
virtual host’s root (i.e. the application will be accessible from the root URL,
|
1134
1405
|
<em>http://www.mycook.com/</em>), or in a sub URI (i.e. the application will be
|
1135
1406
|
accessible from a sub URL, such as <em>http://www.mycook.com/railsapplication</em>).</p></div>
|
1136
1407
|
<div class="admonitionblock">
|
1137
|
-
<table><tr>
|
1408
|
+
<table><tr>
|
1138
1409
|
<td class="icon">
|
1139
|
-
<img src="./images/icons/note.png" alt="Note">
|
1410
|
+
<img src="./images/icons/note.png" alt="Note">
|
1140
1411
|
</td>
|
1141
1412
|
<td class="content">The default <span class="monospaced">RAILS_ENV</span> environment in which deployed Rails applications
|
1142
|
-
are run, is
|
1413
|
+
are run, is “production”. You can change this by changing the
|
1143
1414
|
<a href="#RailsEnv">rails_env</a> configuration option.</td>
|
1144
|
-
</tr></table>
|
1415
|
+
</tr></table>
|
1145
1416
|
</div>
|
1146
1417
|
<div class="sect2">
|
1147
|
-
<h3 id="_deploying_to_a_virtual_host_8217_s_root">3.1. Deploying to a virtual host
|
1418
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_deploying_to_a_virtual_host_8217_s_root" data-comment-topic="deploying-to-a-virtual-host-s-root-1mh24z5">3.1. Deploying to a virtual host’s root</h3>
|
1148
1419
|
<div class="paragraph"><p>Add a <em>server</em> virtual host entry to your Nginx configuration file. The virtual
|
1149
|
-
host
|
1420
|
+
host’s root must point to your Ruby on Rails application’s <em>public</em> folder.</p></div>
|
1150
1421
|
<div class="paragraph"><p>Inside the <em>server</em> block, set <em>passenger_enabled on</em>.</p></div>
|
1151
1422
|
<div class="paragraph"><p>For example:</p></div>
|
1152
1423
|
<div class="listingblock">
|
@@ -1163,11 +1434,12 @@ host’s root must point to your Ruby on Rails application’s <em>publi
|
|
1163
1434
|
|
1164
1435
|
...
|
1165
1436
|
}</pre>
|
1166
|
-
</div
|
1437
|
+
</div>
|
1438
|
+
</div>
|
1167
1439
|
<div class="paragraph"><p>Then restart Nginx. The application has now been deployed.</p></div>
|
1168
1440
|
</div>
|
1169
1441
|
<div class="sect2">
|
1170
|
-
<h3 id="deploying_rails_to_sub_uri">3.2. Deploying to a sub URI</h3>
|
1442
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="deploying_rails_to_sub_uri" data-comment-topic="deploying-to-a-sub-uri-1il2qj7">3.2. Deploying to a sub URI</h3>
|
1171
1443
|
<div class="paragraph"><p>Suppose that you already have a <em>server</em> virtual host entry:</p></div>
|
1172
1444
|
<div class="listingblock">
|
1173
1445
|
<div class="content monospaced">
|
@@ -1182,15 +1454,17 @@ host’s root must point to your Ruby on Rails application’s <em>publi
|
|
1182
1454
|
|
1183
1455
|
...
|
1184
1456
|
}</pre>
|
1185
|
-
</div
|
1457
|
+
</div>
|
1458
|
+
</div>
|
1186
1459
|
<div class="paragraph"><p>And you want your Ruby on Rails application to be accessible from the URL
|
1187
1460
|
<em>http://www.phusion.nl/rails</em>.</p></div>
|
1188
|
-
<div class="paragraph"><p>To do this, make a symlink in the virtual host
|
1189
|
-
point to your Ruby on Rails application
|
1461
|
+
<div class="paragraph"><p>To do this, make a symlink in the virtual host’s document root, and have it
|
1462
|
+
point to your Ruby on Rails application’s <em>public</em> folder. For example:</p></div>
|
1190
1463
|
<div class="listingblock">
|
1191
1464
|
<div class="content monospaced">
|
1192
1465
|
<pre>ln -s /webapps/mycook/public /websites/phusion/rails</pre>
|
1193
|
-
</div
|
1466
|
+
</div>
|
1467
|
+
</div>
|
1194
1468
|
<div class="paragraph"><p>Next, set <em>passenger_enabled on</em> and add a <a href="#PassengerBaseURI">passenger_base_uri</a>
|
1195
1469
|
option to the <em>server</em> block:</p></div>
|
1196
1470
|
<div class="listingblock">
|
@@ -1208,12 +1482,13 @@ option to the <em>server</em> block:</p></div>
|
|
1208
1482
|
|
1209
1483
|
...
|
1210
1484
|
}</pre>
|
1211
|
-
</div
|
1485
|
+
</div>
|
1486
|
+
</div>
|
1212
1487
|
<div class="paragraph"><p>Then restart Nginx. The application has now been deployed.</p></div>
|
1213
1488
|
<div class="admonitionblock">
|
1214
|
-
<table><tr>
|
1489
|
+
<table><tr>
|
1215
1490
|
<td class="icon">
|
1216
|
-
<img src="./images/icons/tip.png" alt="Tip">
|
1491
|
+
<img src="./images/icons/tip.png" alt="Tip">
|
1217
1492
|
</td>
|
1218
1493
|
<td class="content">
|
1219
1494
|
<div class="paragraph"><p>You can deploy multiple Rails applications under a virtual host, by specifying
|
@@ -1226,17 +1501,18 @@ option to the <em>server</em> block:</p></div>
|
|
1226
1501
|
passenger_base_uri /app2;
|
1227
1502
|
passenger_base_uri /app3;
|
1228
1503
|
}</pre>
|
1229
|
-
</div
|
1504
|
+
</div>
|
1505
|
+
</div>
|
1230
1506
|
</td>
|
1231
|
-
</tr></table>
|
1507
|
+
</tr></table>
|
1232
1508
|
</div>
|
1233
1509
|
</div>
|
1234
1510
|
<div class="sect2">
|
1235
|
-
<h3 id="_redeploying_restarting_the_ruby_on_rails_application">3.3. Redeploying (restarting the Ruby on Rails application)</h3>
|
1511
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_redeploying_restarting_the_ruby_on_rails_application" data-comment-topic="redeploying-restarting-the-ruby-on-rails-application--1eso761">3.3. Redeploying (restarting the Ruby on Rails application)</h3>
|
1236
1512
|
<div class="paragraph"><p>Deploying a new version of a Ruby on Rails application is as simple as
|
1237
1513
|
re-uploading the application files, and restarting the application.</p></div>
|
1238
1514
|
<div class="paragraph"><p>There are two ways to restart the application:</p></div>
|
1239
|
-
<div class="olist arabic"><ol class="arabic">
|
1515
|
+
<div class="olist arabic"><ol class="arabic">
|
1240
1516
|
<li>
|
1241
1517
|
<p>
|
1242
1518
|
By restarting Nginx.
|
@@ -1245,7 +1521,7 @@ By restarting Nginx.
|
|
1245
1521
|
<li>
|
1246
1522
|
<p>
|
1247
1523
|
By creating or modifying the file <em>tmp/restart.txt</em> in the Rails
|
1248
|
-
application
|
1524
|
+
application’s <a href="#application_root">root folder</a>. Phusion Passenger will
|
1249
1525
|
automatically restart the application during the next request.
|
1250
1526
|
</p>
|
1251
1527
|
</li>
|
@@ -1255,34 +1531,35 @@ command line:</p></div>
|
|
1255
1531
|
<div class="listingblock">
|
1256
1532
|
<div class="content monospaced">
|
1257
1533
|
<pre>touch /webapps/mycook/tmp/restart.txt</pre>
|
1258
|
-
</div
|
1534
|
+
</div>
|
1535
|
+
</div>
|
1259
1536
|
<div class="paragraph"><p>Please note that, unlike earlier versions of Phusion Passenger, <em>restart.txt</em>
|
1260
1537
|
is not automatically deleted. Phusion Passenger checks whether the timestamp
|
1261
1538
|
of this file has changed in order to determine whether the application should
|
1262
1539
|
be restarted.</p></div>
|
1263
1540
|
</div>
|
1264
1541
|
<div class="sect2">
|
1265
|
-
<h3 id="_migrations">3.4. Migrations</h3>
|
1542
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_migrations" data-comment-topic="migrations-9yyb8w">3.4. Migrations</h3>
|
1266
1543
|
<div class="paragraph"><p>Phusion Passenger is not related to Ruby on Rails migrations in any way. To
|
1267
1544
|
run migrations on your deployment server, please login to your deployment
|
1268
1545
|
server (e.g. with <em>ssh</em>) and type <span class="monospaced">rake db:migrate RAILS_ENV=production</span> in
|
1269
1546
|
a shell console, just like one would normally run migrations.</p></div>
|
1270
1547
|
</div>
|
1271
1548
|
<div class="sect2">
|
1272
|
-
<h3 id="_capistrano_integration">3.5. Capistrano integration</h3>
|
1549
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_capistrano_integration" data-comment-topic="capistrano-integration-1ktunm6">3.5. Capistrano integration</h3>
|
1273
1550
|
<div class="paragraph"><p>See <a href="#capistrano">Capistrano recipe</a>.</p></div>
|
1274
1551
|
</div>
|
1275
1552
|
</div>
|
1276
1553
|
</div>
|
1277
1554
|
<div class="sect1">
|
1278
|
-
<h2 id="deploying_a_rack_app">4. Deploying a Rack-based Ruby application (including Rails >= 3)</h2>
|
1555
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="deploying_a_rack_app" data-comment-topic="deploying-a-rack-based-ruby-application-including-rails-3--12benx3">4. Deploying a Rack-based Ruby application (including Rails >= 3)</h2>
|
1279
1556
|
<div class="sectionbody">
|
1280
1557
|
<div class="paragraph"><p>Phusion Passenger supports arbitrary Ruby web applications that follow the
|
1281
1558
|
<a href="http://rack.rubyforge.org/">Rack</a> interface.</p></div>
|
1282
1559
|
<div class="paragraph"><p>Phusion Passenger assumes that Rack application directories have a certain layout.
|
1283
1560
|
Suppose that you have a Rack application in <em>/webapps/rackapp</em>. Then that
|
1284
1561
|
folder must contain at least three entries:</p></div>
|
1285
|
-
<div class="ulist"><ul>
|
1562
|
+
<div class="ulist"><ul>
|
1286
1563
|
<li>
|
1287
1564
|
<p>
|
1288
1565
|
<em>config.ru</em>, a Rackup file for starting the Rack application. This file must contain
|
@@ -1311,30 +1588,32 @@ folder must contain at least three entries:</p></div>
|
|
1311
1588
|
+-- public/
|
1312
1589
|
|
|
1313
1590
|
+-- tmp/</pre>
|
1314
|
-
</div
|
1591
|
+
</div>
|
1592
|
+
</div>
|
1315
1593
|
<div class="paragraph"><p>Suppose you own the domain <em>www.rackapp.com</em>. You can either deploy your application
|
1316
|
-
to the virtual host
|
1594
|
+
to the virtual host’s root (i.e. the application will be accessible from the root URL,
|
1317
1595
|
<em>http://www.rackapp.com/</em>), or in a sub URI (i.e. the application will be
|
1318
1596
|
accessible from a sub URL, such as <em>http://www.rackapp.com/rackapp</em>).</p></div>
|
1319
1597
|
<div class="admonitionblock">
|
1320
|
-
<table><tr>
|
1598
|
+
<table><tr>
|
1321
1599
|
<td class="icon">
|
1322
|
-
<img src="./images/icons/note.png" alt="Note">
|
1600
|
+
<img src="./images/icons/note.png" alt="Note">
|
1323
1601
|
</td>
|
1324
1602
|
<td class="content">The default <span class="monospaced">RACK_ENV</span> environment in which deployed Rack applications
|
1325
|
-
are run, is
|
1603
|
+
are run, is “production”. You can change this by changing the
|
1326
1604
|
<a href="#RackEnv">rack_env</a> configuration option.</td>
|
1327
|
-
</tr></table>
|
1605
|
+
</tr></table>
|
1328
1606
|
</div>
|
1329
1607
|
<div class="sect2">
|
1330
|
-
<h3 id="_tutorial_example_writing_and_deploying_a_hello_world_rack_application">4.1. Tutorial/example: writing and deploying a Hello World Rack application</h3>
|
1608
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_tutorial_example_writing_and_deploying_a_hello_world_rack_application" data-comment-topic="tutorial-example-writing-and-deploying-a-hello-world-rack-application-1wstx99">4.1. Tutorial/example: writing and deploying a Hello World Rack application</h3>
|
1331
1609
|
<div class="paragraph"><p>First we create a Phusion Passenger-compliant Rack directory structure:</p></div>
|
1332
1610
|
<div class="listingblock">
|
1333
1611
|
<div class="content monospaced">
|
1334
1612
|
<pre>$ mkdir /webapps/rack_example
|
1335
1613
|
$ mkdir /webapps/rack_example/public
|
1336
1614
|
$ mkdir /webapps/rack_example/tmp</pre>
|
1337
|
-
</div
|
1615
|
+
</div>
|
1616
|
+
</div>
|
1338
1617
|
<div class="paragraph"><p>Next, we write a minimal "hello world" Rack application:</p></div>
|
1339
1618
|
<div class="listingblock">
|
1340
1619
|
<div class="content monospaced">
|
@@ -1346,7 +1625,8 @@ app = proc do |env|
|
|
1346
1625
|
[200, { "Content-Type" => "text/html" }, ["hello <b>world</b>"]]
|
1347
1626
|
end
|
1348
1627
|
run app</pre>
|
1349
|
-
</div
|
1628
|
+
</div>
|
1629
|
+
</div>
|
1350
1630
|
<div class="paragraph"><p>Finally, we deploy it by adding the following configuration options to
|
1351
1631
|
the Nginx configuration file:</p></div>
|
1352
1632
|
<div class="listingblock">
|
@@ -1361,14 +1641,15 @@ the Nginx configuration file:</p></div>
|
|
1361
1641
|
}
|
1362
1642
|
...
|
1363
1643
|
}</pre>
|
1364
|
-
</div
|
1365
|
-
|
1644
|
+
</div>
|
1645
|
+
</div>
|
1646
|
+
<div class="paragraph"><p>And we’re done! After an Nginx restart, the above Rack application will be available
|
1366
1647
|
under the URL <em>http://www.rackexample.com/</em>.</p></div>
|
1367
1648
|
</div>
|
1368
1649
|
<div class="sect2">
|
1369
|
-
<h3 id="_deploying_to_a_virtual_host_8217_s_root_2">4.2. Deploying to a virtual host
|
1370
|
-
<div class="paragraph"><p>Add a <em>server</em> virtual host entry to your Nginx configuration file. The virtual host
|
1371
|
-
root must point to your Rack application
|
1650
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_deploying_to_a_virtual_host_8217_s_root_2" data-comment-topic="deploying-to-a-virtual-host-s-root-f02erj">4.2. Deploying to a virtual host’s root</h3>
|
1651
|
+
<div class="paragraph"><p>Add a <em>server</em> virtual host entry to your Nginx configuration file. The virtual host’s
|
1652
|
+
root must point to your Rack application’s <em>public</em> folder. You must also set
|
1372
1653
|
<em>passenger_enabled on</em> in the <em>server</em> block.</p></div>
|
1373
1654
|
<div class="paragraph"><p>For example:</p></div>
|
1374
1655
|
<div class="listingblock">
|
@@ -1383,11 +1664,12 @@ root must point to your Rack application’s <em>public</em> folder. You mus
|
|
1383
1664
|
}
|
1384
1665
|
...
|
1385
1666
|
}</pre>
|
1386
|
-
</div
|
1667
|
+
</div>
|
1668
|
+
</div>
|
1387
1669
|
<div class="paragraph"><p>Then restart Nginx. The application has now been deployed.</p></div>
|
1388
1670
|
</div>
|
1389
1671
|
<div class="sect2">
|
1390
|
-
<h3 id="deploying_rack_to_sub_uri">4.3. Deploying to a sub URI</h3>
|
1672
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="deploying_rack_to_sub_uri" data-comment-topic="deploying-to-a-sub-uri-37q0ou">4.3. Deploying to a sub URI</h3>
|
1391
1673
|
<div class="paragraph"><p>Suppose that you already have a virtual host:</p></div>
|
1392
1674
|
<div class="listingblock">
|
1393
1675
|
<div class="content monospaced">
|
@@ -1403,15 +1685,17 @@ root must point to your Rack application’s <em>public</em> folder. You mus
|
|
1403
1685
|
|
1404
1686
|
...
|
1405
1687
|
}</pre>
|
1406
|
-
</div
|
1688
|
+
</div>
|
1689
|
+
</div>
|
1407
1690
|
<div class="paragraph"><p>And you want your Rack application to be accessible from the URL
|
1408
1691
|
<em>http://www.phusion.nl/rack</em>.</p></div>
|
1409
|
-
<div class="paragraph"><p>To do this, make a symlink in the virtual host
|
1410
|
-
point to your Rack application
|
1692
|
+
<div class="paragraph"><p>To do this, make a symlink in the virtual host’s document root, and have it
|
1693
|
+
point to your Rack application’s <em>public</em> folder. For example:</p></div>
|
1411
1694
|
<div class="listingblock">
|
1412
1695
|
<div class="content monospaced">
|
1413
1696
|
<pre>ln -s /webapps/rackapp/public /websites/phusion/rack</pre>
|
1414
|
-
</div
|
1697
|
+
</div>
|
1698
|
+
</div>
|
1415
1699
|
<div class="paragraph"><p>Next, set <em>passenger_enabled on</em> and add a <a href="#PassengerBaseURI">passenger_base_uri</a>
|
1416
1700
|
option to the <em>server</em> block:</p></div>
|
1417
1701
|
<div class="listingblock">
|
@@ -1429,12 +1713,13 @@ option to the <em>server</em> block:</p></div>
|
|
1429
1713
|
|
1430
1714
|
...
|
1431
1715
|
}</pre>
|
1432
|
-
</div
|
1716
|
+
</div>
|
1717
|
+
</div>
|
1433
1718
|
<div class="paragraph"><p>Then restart Nginx. The application has now been deployed.</p></div>
|
1434
1719
|
<div class="admonitionblock">
|
1435
|
-
<table><tr>
|
1720
|
+
<table><tr>
|
1436
1721
|
<td class="icon">
|
1437
|
-
<img src="./images/icons/tip.png" alt="Tip">
|
1722
|
+
<img src="./images/icons/tip.png" alt="Tip">
|
1438
1723
|
</td>
|
1439
1724
|
<td class="content">
|
1440
1725
|
<div class="paragraph"><p>You can deploy multiple Rack applications under a virtual host, by specifying
|
@@ -1447,17 +1732,18 @@ option to the <em>server</em> block:</p></div>
|
|
1447
1732
|
passenger_base_uri /app2;
|
1448
1733
|
passenger_base_uri /app3;
|
1449
1734
|
}</pre>
|
1450
|
-
</div
|
1735
|
+
</div>
|
1736
|
+
</div>
|
1451
1737
|
</td>
|
1452
|
-
</tr></table>
|
1738
|
+
</tr></table>
|
1453
1739
|
</div>
|
1454
1740
|
</div>
|
1455
1741
|
<div class="sect2">
|
1456
|
-
<h3 id="_redeploying_restarting_the_rack_application">4.4. Redeploying (restarting the Rack application)</h3>
|
1742
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_redeploying_restarting_the_rack_application" data-comment-topic="redeploying-restarting-the-rack-application--xnbfam">4.4. Redeploying (restarting the Rack application)</h3>
|
1457
1743
|
<div class="paragraph"><p>Deploying a new version of a Rack application is as simple as
|
1458
1744
|
re-uploading the application files, and restarting the application.</p></div>
|
1459
1745
|
<div class="paragraph"><p>There are two ways to restart the application:</p></div>
|
1460
|
-
<div class="olist arabic"><ol class="arabic">
|
1746
|
+
<div class="olist arabic"><ol class="arabic">
|
1461
1747
|
<li>
|
1462
1748
|
<p>
|
1463
1749
|
By restarting Nginx.
|
@@ -1466,7 +1752,7 @@ By restarting Nginx.
|
|
1466
1752
|
<li>
|
1467
1753
|
<p>
|
1468
1754
|
By creating or modifying the file <em>tmp/restart.txt</em> in the Rack
|
1469
|
-
application
|
1755
|
+
application’s <a href="#application_root">root folder</a>. Phusion Passenger will
|
1470
1756
|
automatically restart the application.
|
1471
1757
|
</p>
|
1472
1758
|
</li>
|
@@ -1476,13 +1762,14 @@ command line:</p></div>
|
|
1476
1762
|
<div class="listingblock">
|
1477
1763
|
<div class="content monospaced">
|
1478
1764
|
<pre>touch /webapps/rackapp/tmp/restart.txt</pre>
|
1479
|
-
</div
|
1765
|
+
</div>
|
1766
|
+
</div>
|
1480
1767
|
</div>
|
1481
1768
|
<div class="sect2">
|
1482
|
-
<h3 id="_rackup_specifications_for_various_web_frameworks">4.5. Rackup specifications for various web frameworks</h3>
|
1769
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_rackup_specifications_for_various_web_frameworks" data-comment-topic="rackup-specifications-for-various-web-frameworks-1a2cs41">4.5. Rackup specifications for various web frameworks</h3>
|
1483
1770
|
<div class="paragraph"><p>This subsection shows example <em>config.ru</em> files for various web frameworks.</p></div>
|
1484
1771
|
<div class="sect3">
|
1485
|
-
<h4 id="_camping">4.5.1. Camping</h4>
|
1772
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_camping" data-comment-topic="camping-16vz2yb">4.5.1. Camping</h4>
|
1486
1773
|
<div class="listingblock">
|
1487
1774
|
<div class="content monospaced">
|
1488
1775
|
<pre>require 'rubygems'
|
@@ -1496,11 +1783,12 @@ Camping.goes :Blog
|
|
1496
1783
|
##### End Camping application
|
1497
1784
|
|
1498
1785
|
run Rack::Adapter::Camping.new(Blog)</pre>
|
1499
|
-
</div
|
1786
|
+
</div>
|
1787
|
+
</div>
|
1500
1788
|
<div class="paragraph"><p>For Camping versions 2.0 and up, using <span class="monospaced">run Blog</span> as the final line will do.</p></div>
|
1501
1789
|
</div>
|
1502
1790
|
<div class="sect3">
|
1503
|
-
<h4 id="_halcyon">4.5.2. Halcyon</h4>
|
1791
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_halcyon" data-comment-topic="halcyon-1benlfl">4.5.2. Halcyon</h4>
|
1504
1792
|
<div class="listingblock">
|
1505
1793
|
<div class="content monospaced">
|
1506
1794
|
<pre>require 'rubygems'
|
@@ -1508,10 +1796,11 @@ require 'halcyon'
|
|
1508
1796
|
$LOAD_PATH.unshift(Halcyon.root / 'lib')
|
1509
1797
|
Halcyon::Runner.load_config Halcyon.root/'config'/'config.yml'
|
1510
1798
|
run Halcyon::Runner.new</pre>
|
1511
|
-
</div
|
1799
|
+
</div>
|
1800
|
+
</div>
|
1512
1801
|
</div>
|
1513
1802
|
<div class="sect3">
|
1514
|
-
<h4 id="_mack">4.5.3. Mack</h4>
|
1803
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_mack" data-comment-topic="mack-1ezijq6">4.5.3. Mack</h4>
|
1515
1804
|
<div class="listingblock">
|
1516
1805
|
<div class="content monospaced">
|
1517
1806
|
<pre>ENV["MACK_ENV"] = ENV["RACK_ENV"]
|
@@ -1519,10 +1808,11 @@ load("Rakefile")
|
|
1519
1808
|
require 'rubygems'
|
1520
1809
|
require 'mack'
|
1521
1810
|
run Mack::Utils::Server.build_app</pre>
|
1522
|
-
</div
|
1811
|
+
</div>
|
1812
|
+
</div>
|
1523
1813
|
</div>
|
1524
1814
|
<div class="sect3">
|
1525
|
-
<h4 id="_merb">4.5.4. Merb</h4>
|
1815
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_merb" data-comment-topic="merb-ddsh55">4.5.4. Merb</h4>
|
1526
1816
|
<div class="listingblock">
|
1527
1817
|
<div class="content monospaced">
|
1528
1818
|
<pre>require 'rubygems'
|
@@ -1537,10 +1827,11 @@ Merb.root = Merb::Config[:merb_root]
|
|
1537
1827
|
Merb::BootLoader.run
|
1538
1828
|
|
1539
1829
|
run Merb::Rack::Application.new</pre>
|
1540
|
-
</div
|
1830
|
+
</div>
|
1831
|
+
</div>
|
1541
1832
|
</div>
|
1542
1833
|
<div class="sect3">
|
1543
|
-
<h4 id="_ramaze">4.5.5. Ramaze</h4>
|
1834
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_ramaze" data-comment-topic="ramaze-1p2zod">4.5.5. Ramaze</h4>
|
1544
1835
|
<div class="listingblock">
|
1545
1836
|
<div class="content monospaced">
|
1546
1837
|
<pre>require "rubygems"
|
@@ -1549,10 +1840,11 @@ Ramaze.trait[:essentials].delete Ramaze::Adapter
|
|
1549
1840
|
require "start"
|
1550
1841
|
Ramaze.start!
|
1551
1842
|
run Ramaze::Adapter::Base</pre>
|
1552
|
-
</div
|
1843
|
+
</div>
|
1844
|
+
</div>
|
1553
1845
|
</div>
|
1554
1846
|
<div class="sect3">
|
1555
|
-
<h4 id="_sinatra">4.5.6. Sinatra</h4>
|
1847
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_sinatra" data-comment-topic="sinatra-a7u9ag">4.5.6. Sinatra</h4>
|
1556
1848
|
<div class="listingblock">
|
1557
1849
|
<div class="content monospaced">
|
1558
1850
|
<pre>require 'rubygems'
|
@@ -1560,59 +1852,61 @@ require 'sinatra'
|
|
1560
1852
|
require 'app.rb'
|
1561
1853
|
|
1562
1854
|
run Sinatra::Application</pre>
|
1563
|
-
</div
|
1855
|
+
</div>
|
1856
|
+
</div>
|
1564
1857
|
</div>
|
1565
1858
|
</div>
|
1566
1859
|
</div>
|
1567
1860
|
</div>
|
1568
1861
|
<div class="sect1">
|
1569
|
-
<h2 id="_configuring_phusion_passenger">5. Configuring Phusion Passenger</h2>
|
1862
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_configuring_phusion_passenger" data-comment-topic="configuring-phusion-passenger-1g1svey">5. Configuring Phusion Passenger</h2>
|
1570
1863
|
<div class="sectionbody">
|
1571
1864
|
<div class="paragraph"><p>After installation, Phusion Passenger does not need any further configurations.
|
1572
1865
|
Nevertheless, the system administrator may be interested in changing
|
1573
|
-
Phusion Passenger
|
1866
|
+
Phusion Passenger’s behavior. Phusion Passenger supports the following configuration
|
1574
1867
|
options in the Nginx configuration file:</p></div>
|
1575
1868
|
<div class="sect2">
|
1576
|
-
<h3 id="_passenger_root_lt_directory_gt">5.1. passenger_root <directory></h3>
|
1869
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_passenger_root_lt_directory_gt" data-comment-topic="passenger-root-directory--bqvhhz">5.1. passenger_root <directory></h3>
|
1577
1870
|
<div class="paragraph"><p>The location to the Phusion Passenger root directory. This configuration option
|
1578
1871
|
is essential to Phusion Passenger, and allows Phusion Passenger to locate its own
|
1579
1872
|
data files. The correct value is given by the installer.</p></div>
|
1580
|
-
<div class="paragraph"><p>If you
|
1873
|
+
<div class="paragraph"><p>If you’ve moved Phusion Passenger to a different directory then you need to update
|
1581
1874
|
this option as well. Please read
|
1582
1875
|
<a href="#moving_phusion_passenger">Moving Phusion Passenger to a different directory</a> for more information.</p></div>
|
1583
1876
|
<div class="paragraph"><p>This required option may only occur once, in the <em>http</em> configuration block.</p></div>
|
1584
1877
|
</div>
|
1585
1878
|
<div class="sect2">
|
1586
|
-
<h3 id="_passenger_ruby_lt_filename_gt">5.2. passenger_ruby <filename></h3>
|
1879
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_passenger_ruby_lt_filename_gt" data-comment-topic="passenger-ruby-filename--1gnok5k">5.2. passenger_ruby <filename></h3>
|
1587
1880
|
<div class="paragraph"><p>This option allows one to specify the Ruby interpreter to use.</p></div>
|
1588
1881
|
<div class="paragraph"><p>This option may only occur once, in the <em>http</em> configuration block.
|
1589
1882
|
The default is <em>ruby</em>.</p></div>
|
1590
1883
|
</div>
|
1591
1884
|
<div class="sect2">
|
1592
|
-
<h3 id="PassengerSpawnMethod">5.3. passenger_spawn_method <string></h3>
|
1885
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="PassengerSpawnMethod" data-comment-topic="passenger-spawn-method-string--1sc6njl">5.3. passenger_spawn_method <string></h3>
|
1593
1886
|
<div class="admonitionblock">
|
1594
|
-
<table><tr>
|
1887
|
+
<table><tr>
|
1595
1888
|
<td class="icon">
|
1596
|
-
<img src="./images/icons/tip.png" alt="Tip">
|
1889
|
+
<img src="./images/icons/tip.png" alt="Tip">
|
1597
1890
|
</td>
|
1598
1891
|
<td class="content">
|
1599
1892
|
<div class="title">"What spawn method should I use?"</div>
|
1600
|
-
<div class="paragraph"><p>This subsection attempts to describe spawn methods, but it
|
1601
|
-
understand it, as it
|
1893
|
+
<div class="paragraph"><p>This subsection attempts to describe spawn methods, but it’s okay if you don’t (want to)
|
1894
|
+
understand it, as it’s mostly a technical detail. You can basically follow this rule of thumb:</p></div>
|
1602
1895
|
<div class="sidebarblock">
|
1603
1896
|
<div class="content">
|
1604
1897
|
<div class="paragraph"><p>If your application works on Mongrel, but not on Phusion Passenger, then set
|
1605
1898
|
<span class="monospaced">passenger_spawn_method</span> to <em>conservative</em>. Otherwise, leave it at <em>smart-lv2</em> (the default).</p></div>
|
1606
|
-
</div
|
1899
|
+
</div>
|
1900
|
+
</div>
|
1607
1901
|
<div class="paragraph"><p>However, we do recommend you to try to understand it. The <em>smart</em> and <em>smart-lv2</em> spawn
|
1608
1902
|
methods bring many benefits.</p></div>
|
1609
1903
|
</td>
|
1610
|
-
</tr></table>
|
1904
|
+
</tr></table>
|
1611
1905
|
</div>
|
1612
1906
|
<div class="paragraph"><p>Internally, Phusion Passenger spawns multiple Ruby application processes in order to handle
|
1613
1907
|
requests. But there are multiple ways with which processes can be spawned, each having
|
1614
1908
|
its own set of pros and cons. Supported spawn methods are:</p></div>
|
1615
|
-
<div class="dlist"><dl>
|
1909
|
+
<div class="dlist"><dl>
|
1616
1910
|
<dt class="hdlist1">
|
1617
1911
|
<em>smart</em>
|
1618
1912
|
</dt>
|
@@ -1628,7 +1922,7 @@ This can significantly decrease spawn time (by as much as 90%). And, when Ruby E
|
|
1628
1922
|
Edition is used, <a href="#reducing_memory_usage">memory usage can be reduced by 33% on average</a>.</p></div>
|
1629
1923
|
<div class="paragraph"><p><strong>Cons:</strong>
|
1630
1924
|
Some applications and libraries are not compatible with smart spawning.
|
1631
|
-
If that
|
1925
|
+
If that’s the case for your application, then you should use <em>conservative</em> as
|
1632
1926
|
spawning method. Please read <a href="#spawning_methods_explained">Spawning methods explained</a>
|
1633
1927
|
for possible compatibility issues.</p></div>
|
1634
1928
|
</dd>
|
@@ -1666,11 +1960,11 @@ and libraries.</p></div>
|
|
1666
1960
|
<div class="paragraph"><p><strong>Cons:</strong>
|
1667
1961
|
Much slower than smart spawning. Every spawn action will be equally slow, though no slower than
|
1668
1962
|
the startup time of a single server in Mongrel Cluster. Conservative spawning will also
|
1669
|
-
render <a href="#reducing_memory_usage">Ruby Enterprise Edition
|
1963
|
+
render <a href="#reducing_memory_usage">Ruby Enterprise Edition’s memory reduction technology</a> useless.</p></div>
|
1670
1964
|
</dd>
|
1671
1965
|
</dl></div>
|
1672
1966
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1673
|
-
<div class="ulist"><ul>
|
1967
|
+
<div class="ulist"><ul>
|
1674
1968
|
<li>
|
1675
1969
|
<p>
|
1676
1970
|
In the <em>http</em> configuration block.
|
@@ -1695,9 +1989,9 @@ In an <em>if</em> configuration scope.
|
|
1695
1989
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>smart-lv2</em>.</p></div>
|
1696
1990
|
</div>
|
1697
1991
|
<div class="sect2">
|
1698
|
-
<h3 id="_important_deployment_options">5.4. Important deployment options</h3>
|
1992
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_important_deployment_options" data-comment-topic="important-deployment-options-av567">5.4. Important deployment options</h3>
|
1699
1993
|
<div class="sect3">
|
1700
|
-
<h4 id="_passenger_enabled_lt_on_off_gt">5.4.1. passenger_enabled <on|off></h4>
|
1994
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_enabled_lt_on_off_gt" data-comment-topic="passenger-enabled-on-off--1rpb2t7">5.4.1. passenger_enabled <on|off></h4>
|
1701
1995
|
<div class="paragraph"><p>This option may be specified in the <em>http</em> configuration block, a
|
1702
1996
|
<em>server</em> configuration block, a <em>location</em> configuration block or
|
1703
1997
|
an <em>if</em> configuration scope, to enable or disable Phusion Passenger
|
@@ -1709,7 +2003,7 @@ and <a href="#deploying_a_rack_app">Deploying a Rack-based Ruby application</a>
|
|
1709
2003
|
for examples.</p></div>
|
1710
2004
|
</div>
|
1711
2005
|
<div class="sect3">
|
1712
|
-
<h4 id="PassengerBaseURI">5.4.2. passenger_base_uri <uri></h4>
|
2006
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerBaseURI" data-comment-topic="passenger-base-uri-uri--1xtuo50">5.4.2. passenger_base_uri <uri></h4>
|
1713
2007
|
<div class="paragraph"><p>Used to specify that the given URI is an distinct application that should
|
1714
2008
|
be served by Phusion Passenger. This option can be used for both Rails and
|
1715
2009
|
Rack applications. See <a href="#deploying_rails_to_sub_uri">Deploying Rails to a sub URI</a>
|
@@ -1717,7 +2011,7 @@ for an example.</p></div>
|
|
1717
2011
|
<div class="paragraph"><p>It is allowed to specify this option multiple times. Do this to deploy multiple
|
1718
2012
|
applications in different sub-URIs under the same virtual host.</p></div>
|
1719
2013
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1720
|
-
<div class="ulist"><ul>
|
2014
|
+
<div class="ulist"><ul>
|
1721
2015
|
<li>
|
1722
2016
|
<p>
|
1723
2017
|
In the <em>http</em> configuration block.
|
@@ -1742,12 +2036,12 @@ In an <em>if</em> configuration scope.
|
|
1742
2036
|
</div>
|
1743
2037
|
</div>
|
1744
2038
|
<div class="sect2">
|
1745
|
-
<h3 id="_connection_handling_options">5.5. Connection handling options</h3>
|
2039
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_connection_handling_options" data-comment-topic="connection-handling-options-8jgq90">5.5. Connection handling options</h3>
|
1746
2040
|
<div class="sect3">
|
1747
|
-
<h4 id="PassengerUseGlobalQueue">5.5.1. passenger_use_global_queue <on|off></h4>
|
2041
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerUseGlobalQueue" data-comment-topic="passenger-use-global-queue-on-off--14h9n22">5.5.1. passenger_use_global_queue <on|off></h4>
|
1748
2042
|
<div class="paragraph"><p>Turns the use of global queuing on or off.</p></div>
|
1749
2043
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1750
|
-
<div class="ulist"><ul>
|
2044
|
+
<div class="ulist"><ul>
|
1751
2045
|
<li>
|
1752
2046
|
<p>
|
1753
2047
|
In the <em>http</em> configuration block.
|
@@ -1771,26 +2065,32 @@ In an <em>if</em> configuration scope.
|
|
1771
2065
|
</ul></div>
|
1772
2066
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>on</em>.</p></div>
|
1773
2067
|
<div class="paragraph"><p><em>This feature is sponsored by <a href="http://www.37signals.com/">37signals</a>.</em></p></div>
|
1774
|
-
<div class="paragraph"
|
2068
|
+
<div class="paragraph">
|
2069
|
+
<div class="title">What does this option do?</div>
|
2070
|
+
<p>Recall that Phusion Passenger spawns multiple backend processes (e.g. multiple
|
1775
2071
|
Ruby on Rails processes), each which processes HTTP requests serially. One of
|
1776
|
-
Phusion Passenger
|
2072
|
+
Phusion Passenger’s jobs is to forward HTTP requests to a suitable backend
|
1777
2073
|
process. A backend process may take an arbitrary amount of time to process a
|
1778
2074
|
specific HTTP request. If the websites are (temporarily) under high load, and
|
1779
2075
|
the backend processes cannot process the requests fast enough, then some
|
1780
|
-
requests may have to be queued.</p
|
2076
|
+
requests may have to be queued.</p>
|
2077
|
+
</div>
|
1781
2078
|
<div class="paragraph"><p>If global queuing is turned off, then Phusion Passenger will use <em>fair load
|
1782
2079
|
balancing</em>. This means that each backend process will have its own private
|
1783
2080
|
queue. Phusion Passenger will forward an HTTP request to the backend process
|
1784
2081
|
that has the least amount of requests in its queue.</p></div>
|
1785
2082
|
<div class="paragraph"><p>If global queuing is turned on, then Phusion Passenger will use a global queue
|
1786
|
-
that
|
2083
|
+
that’s shared between all backend processes. If an HTTP request comes in, and
|
1787
2084
|
all the backend processes are still busy, then Phusion Passenger will wait until
|
1788
2085
|
at least one backend process is done, and will then forward the request to that
|
1789
2086
|
process.</p></div>
|
1790
|
-
<div class="paragraph"
|
1791
|
-
|
2087
|
+
<div class="paragraph">
|
2088
|
+
<div class="title">When to turn on global queuing?</div>
|
2089
|
+
<p>You should turn on global queuing if one of your web applications may have
|
2090
|
+
long-running requests.</p>
|
2091
|
+
</div>
|
1792
2092
|
<div class="paragraph"><p>For example suppose that:</p></div>
|
1793
|
-
<div class="ulist"><ul>
|
2093
|
+
<div class="ulist"><ul>
|
1794
2094
|
<li>
|
1795
2095
|
<p>
|
1796
2096
|
global queuing is turned off.
|
@@ -1798,7 +2098,7 @@ global queuing is turned off.
|
|
1798
2098
|
</li>
|
1799
2099
|
<li>
|
1800
2100
|
<p>
|
1801
|
-
we
|
2101
|
+
we’re currently in a state where all backend processes have 3 requests in
|
1802
2102
|
their queue, except for a single backend process, which has 1 request in its
|
1803
2103
|
queue.
|
1804
2104
|
</p>
|
@@ -1811,19 +2111,21 @@ we’re currently in a state where all backend processes have 3 requests in
|
|
1811
2111
|
Backend process B: [*** ] (3 requests in queue)
|
1812
2112
|
Backend process C: [*** ] (3 requests in queue)
|
1813
2113
|
Backend process D: [*** ] (3 requests in queue)</pre>
|
1814
|
-
</div
|
2114
|
+
</div>
|
2115
|
+
</div>
|
1815
2116
|
<div class="paragraph"><p>Each process is currently serving short-running requests.</p></div>
|
1816
2117
|
<div class="paragraph"><p>Phusion Passenger will forward the next request to backend process A. A will
|
1817
|
-
now have 2 items in its queue. We
|
2118
|
+
now have 2 items in its queue. We’ll mark this new request with an X:</p></div>
|
1818
2119
|
<div class="listingblock">
|
1819
2120
|
<div class="content monospaced">
|
1820
2121
|
<pre>Backend process A: [*X ] (2 request in queue)
|
1821
2122
|
Backend process B: [*** ] (3 requests in queue)
|
1822
2123
|
Backend process C: [*** ] (3 requests in queue)
|
1823
2124
|
Backend process D: [*** ] (3 requests in queue)</pre>
|
1824
|
-
</div
|
1825
|
-
|
1826
|
-
|
2125
|
+
</div>
|
2126
|
+
</div>
|
2127
|
+
<div class="paragraph"><p>Assuming that B, C and D still aren’t done with their current request, the next
|
2128
|
+
HTTP request - let’s call this Y - will be forwarded to backend process A as
|
1827
2129
|
well, because it has the least number of items in its queue:</p></div>
|
1828
2130
|
<div class="listingblock">
|
1829
2131
|
<div class="content monospaced">
|
@@ -1831,29 +2133,30 @@ well, because it has the least number of items in its queue:</p></div>
|
|
1831
2133
|
Backend process B: [*** ] (3 requests in queue)
|
1832
2134
|
Backend process C: [*** ] (3 requests in queue)
|
1833
2135
|
Backend process D: [*** ] (3 requests in queue)</pre>
|
1834
|
-
</div
|
2136
|
+
</div>
|
2137
|
+
</div>
|
1835
2138
|
<div class="paragraph"><p>But if request X happens to be a long-running request that needs 60 seconds to
|
1836
|
-
complete, then we
|
2139
|
+
complete, then we’ll have a problem. Y won’t be processed for at least 60
|
1837
2140
|
seconds. It would have been a better idea if Y was forward to processes B, C or
|
1838
2141
|
D instead, because they only have short-living requests in their queues.</p></div>
|
1839
2142
|
<div class="paragraph"><p>This problem will be avoided entirely if you turn global queuing on. With global
|
1840
2143
|
queuing, all backend processes will share the same queue. The first backend
|
1841
2144
|
process that becomes available will take from the queue, and so this
|
1842
|
-
|
2145
|
+
“queuing-behind-long-running-request” problem will never occur.</p></div>
|
1843
2146
|
</div>
|
1844
2147
|
<div class="sect3">
|
1845
|
-
<h4 id="_passenger_ignore_client_abort_lt_on_off_gt">5.5.2. passenger_ignore_client_abort <on|off></h4>
|
2148
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_ignore_client_abort_lt_on_off_gt" data-comment-topic="passenger-ignore-client-abort-on-off--19bapt2">5.5.2. passenger_ignore_client_abort <on|off></h4>
|
1846
2149
|
<div class="paragraph"><p>Normally, when the HTTP client aborts the connection (e.g. when the user clicked on "Stop"
|
1847
2150
|
in the browser), the connection with the application process will be closed too. If the
|
1848
2151
|
application process continues to send its response, then that will result in EPIPE errors
|
1849
|
-
in the application, which will be printed in the error log if the application doesn
|
2152
|
+
in the application, which will be printed in the error log if the application doesn’t
|
1850
2153
|
handle them gracefully.</p></div>
|
1851
2154
|
<div class="paragraph"><p>If this option is turned on then upon client abort Phusion Passenger will continue to
|
1852
|
-
read the application process
|
1853
|
-
EPIPE errors but it
|
2155
|
+
read the application process’s response while discarding all the read data. This prevents
|
2156
|
+
EPIPE errors but it’ll also mean the backend process will be unavailable for new requests
|
1854
2157
|
until it is done sending its response.</p></div>
|
1855
2158
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1856
|
-
<div class="ulist"><ul>
|
2159
|
+
<div class="ulist"><ul>
|
1857
2160
|
<li>
|
1858
2161
|
<p>
|
1859
2162
|
In the <em>http</em> configuration block.
|
@@ -1878,10 +2181,10 @@ In an <em>if</em> configuration scope.
|
|
1878
2181
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>off</em>.</p></div>
|
1879
2182
|
</div>
|
1880
2183
|
<div class="sect3">
|
1881
|
-
<h4 id="_passenger_set_cgi_param_lt_cgi_environment_name_gt_lt_value_gt">5.5.3. passenger_set_cgi_param <CGI environment name> <value></h4>
|
2184
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_set_cgi_param_lt_cgi_environment_name_gt_lt_value_gt" data-comment-topic="passenger-set-cgi-param-cgi-environment-name-value--rx9gc0">5.5.3. passenger_set_cgi_param <CGI environment name> <value></h4>
|
1882
2185
|
<div class="paragraph"><p>Allows one to define additional CGI environment variables to pass to the backend
|
1883
|
-
application. This is equivalent to ngx_http_fastcgi_module
|
1884
|
-
directive, and is comparable to ngx_http_proxy_module
|
2186
|
+
application. This is equivalent to ngx_http_fastcgi_module’s <em>fastcgi_param</em>
|
2187
|
+
directive, and is comparable to ngx_http_proxy_module’s <em>proxy_set_header</em> option.
|
1885
2188
|
Nginx variables in the value are interpolated.</p></div>
|
1886
2189
|
<div class="paragraph"><p>For example:</p></div>
|
1887
2190
|
<div class="listingblock">
|
@@ -1891,7 +2194,8 @@ passenger_set_cgi_param APP_NAME "my super blog";
|
|
1891
2194
|
|
1892
2195
|
# Nginx variables are interpolated.
|
1893
2196
|
passenger_set_cgi_param EXTRA_REQUEST_METHOD method=$request_method;</pre>
|
1894
|
-
</div
|
2197
|
+
</div>
|
2198
|
+
</div>
|
1895
2199
|
<div class="paragraph"><p>If you want to set an HTTP header, then you must set it in the CGI environment name
|
1896
2200
|
format, i.e. <em>HTTP_*</em>:</p></div>
|
1897
2201
|
<div class="listingblock">
|
@@ -1901,9 +2205,10 @@ passenger_set_cgi_param X-Forwarded-For 127.0.0.2;
|
|
1901
2205
|
|
1902
2206
|
# Instead, write it like this:
|
1903
2207
|
passenger_set_cgi_param HTTP_X_FORWARDED_FOR 127.0.0.2;</pre>
|
1904
|
-
</div
|
2208
|
+
</div>
|
2209
|
+
</div>
|
1905
2210
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1906
|
-
<div class="ulist"><ul>
|
2211
|
+
<div class="ulist"><ul>
|
1907
2212
|
<li>
|
1908
2213
|
<p>
|
1909
2214
|
In the <em>http</em> configuration block.
|
@@ -1927,7 +2232,7 @@ In an <em>if</em> configuration scope.
|
|
1927
2232
|
</ul></div>
|
1928
2233
|
</div>
|
1929
2234
|
<div class="sect3">
|
1930
|
-
<h4 id="_passenger_pass_header_lt_header_name_gt">5.5.4. passenger_pass_header <header name></h4>
|
2235
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_pass_header_lt_header_name_gt" data-comment-topic="passenger-pass-header-header-name--1cg31je">5.5.4. passenger_pass_header <header name></h4>
|
1931
2236
|
<div class="paragraph"><p>Some headers generated by backend applications are not forwarded to the HTTP client,
|
1932
2237
|
e.g. <em>X-Accel-Redirect</em> which is directly processed by Nginx and then discarded from
|
1933
2238
|
the final response. This directive allows one to force Nginx to pass those headers
|
@@ -1938,9 +2243,10 @@ anyway, similar to how <em>proxy_pass_header</em> works.</p></div>
|
|
1938
2243
|
<pre>location / {
|
1939
2244
|
passenger_pass_header X-Accel-Redirect;
|
1940
2245
|
}</pre>
|
1941
|
-
</div
|
2246
|
+
</div>
|
2247
|
+
</div>
|
1942
2248
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
1943
|
-
<div class="ulist"><ul>
|
2249
|
+
<div class="ulist"><ul>
|
1944
2250
|
<li>
|
1945
2251
|
<p>
|
1946
2252
|
In the <em>http</em> configuration block.
|
@@ -1964,12 +2270,12 @@ In an <em>if</em> configuration scope.
|
|
1964
2270
|
</ul></div>
|
1965
2271
|
</div>
|
1966
2272
|
<div class="sect3">
|
1967
|
-
<h4 id="_passenger_buffer_response_lt_on_off_gt">5.5.5. passenger_buffer_response <on|off></h4>
|
2273
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_buffer_response_lt_on_off_gt" data-comment-topic="passenger-buffer-response-on-off--1twmh51">5.5.5. passenger_buffer_response <on|off></h4>
|
1968
2274
|
<div class="paragraph"><p>When turned on, application-generated responses are buffered in memory and also on
|
1969
2275
|
disk if the response is larger than a certain threshold. By buffering responses,
|
1970
2276
|
protection is provided against slow HTTP clients that can not read your response
|
1971
2277
|
immediately.</p></div>
|
1972
|
-
<div class="paragraph"><p>For example, consider an HTTP client that
|
2278
|
+
<div class="paragraph"><p>For example, consider an HTTP client that’s on a dial-up modem link, and your
|
1973
2279
|
application instance generates a 2 MB response. If response buffering is turned
|
1974
2280
|
off then your application instance will be blocked until the entire 2 MB has been
|
1975
2281
|
sent out to the HTTP client. This disallows your application instance to do any useful
|
@@ -1986,8 +2292,9 @@ impossible. Consider for example this piece of Rails code:</p></div>
|
|
1986
2292
|
sleep 1
|
1987
2293
|
end
|
1988
2294
|
}</pre>
|
1989
|
-
</div
|
1990
|
-
|
2295
|
+
</div>
|
2296
|
+
</div>
|
2297
|
+
<div class="paragraph"><p>…or this piece of Rack code:</p></div>
|
1991
2298
|
<div class="listingblock">
|
1992
2299
|
<div class="content monospaced">
|
1993
2300
|
<pre>class Response
|
@@ -2002,7 +2309,8 @@ end
|
|
2002
2309
|
app = lambda do |env|
|
2003
2310
|
[200, { "Content-Type" => "text/plain" }, Response.new]
|
2004
2311
|
end</pre>
|
2005
|
-
</div
|
2312
|
+
</div>
|
2313
|
+
</div>
|
2006
2314
|
<div class="paragraph"><p>When response buffering is turned on, Phusion Passenger will wait until
|
2007
2315
|
the application is done sending the entire response before forwarding it
|
2008
2316
|
to the client. The client will not receive anything for 10 seconds,
|
@@ -2010,7 +2318,7 @@ after which it receives the entire response at once.
|
|
2010
2318
|
When response buffering is turned off, it works as expected: the client
|
2011
2319
|
receives an "entry X" message every second for 10 seconds.</p></div>
|
2012
2320
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2013
|
-
<div class="ulist"><ul>
|
2321
|
+
<div class="ulist"><ul>
|
2014
2322
|
<li>
|
2015
2323
|
<p>
|
2016
2324
|
In the <em>http</em> configuration block.
|
@@ -2035,34 +2343,34 @@ In an <em>if</em> configuration scope.
|
|
2035
2343
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>on</em>.</p></div>
|
2036
2344
|
</div>
|
2037
2345
|
<div class="sect3">
|
2038
|
-
<h4 id="_passenger_buffer_size">5.5.6. passenger_buffer_size</h4>
|
2346
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_buffer_size" data-comment-topic="passenger-buffer-size-1jfkq87">5.5.6. passenger_buffer_size</h4>
|
2039
2347
|
</div>
|
2040
2348
|
<div class="sect3">
|
2041
|
-
<h4 id="_passenger_buffers">5.5.7. passenger_buffers</h4>
|
2349
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_buffers" data-comment-topic="passenger-buffers-12q1he5">5.5.7. passenger_buffers</h4>
|
2042
2350
|
</div>
|
2043
2351
|
<div class="sect3">
|
2044
|
-
<h4 id="_passenger_busy_buffer_size">5.5.8. passenger_busy_buffer_size</h4>
|
2045
|
-
<div class="paragraph"><p>These options have the same effect as proxy_module
|
2352
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_busy_buffer_size" data-comment-topic="passenger-busy-buffer-size-1gde265">5.5.8. passenger_busy_buffer_size</h4>
|
2353
|
+
<div class="paragraph"><p>These options have the same effect as proxy_module’s similarly named options.
|
2046
2354
|
They can be used to modify the maximum allowed HTTP header size.</p></div>
|
2047
2355
|
</div>
|
2048
2356
|
</div>
|
2049
2357
|
<div class="sect2">
|
2050
|
-
<h3 id="_security_options">5.6. Security options</h3>
|
2358
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_security_options" data-comment-topic="security-options-1bv93g4">5.6. Security options</h3>
|
2051
2359
|
<div class="sect3">
|
2052
|
-
<h4 id="PassengerUserSwitching">5.6.1. passenger_user_switching <on|off></h4>
|
2360
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerUserSwitching" data-comment-topic="passenger-user-switching-on-off--1p37u3l">5.6.1. passenger_user_switching <on|off></h4>
|
2053
2361
|
<div class="paragraph"><p>Whether to enable <a href="#user_switching">user switching support</a>.</p></div>
|
2054
2362
|
<div class="paragraph"><p>This option may only occur once, in the <em>http</em> configuration block.
|
2055
2363
|
The default value is <em>on</em>.</p></div>
|
2056
2364
|
</div>
|
2057
2365
|
<div class="sect3">
|
2058
|
-
<h4 id="_passenger_user_lt_username_gt">5.6.2. passenger_user <username></h4>
|
2366
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_user_lt_username_gt" data-comment-topic="passenger-user-username--b06ur7">5.6.2. passenger_user <username></h4>
|
2059
2367
|
<div class="paragraph"><p>If <a href="#user_switching">user switching support</a> is enabled, then Phusion Passenger will
|
2060
2368
|
by default run the web application as the owner of the file <em>config/environment.rb</em>
|
2061
2369
|
(for Rails apps) or <em>config.ru</em> (for Rack apps). This option allows you to override
|
2062
2370
|
that behavior and explicitly set a user to run the web application as, regardless
|
2063
2371
|
of the ownership of <em>environment.rb</em>/<em>config.ru</em>.</p></div>
|
2064
2372
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2065
|
-
<div class="ulist"><ul>
|
2373
|
+
<div class="ulist"><ul>
|
2066
2374
|
<li>
|
2067
2375
|
<p>
|
2068
2376
|
In the <em>http</em> configuration block.
|
@@ -2087,16 +2395,16 @@ In an <em>if</em> configuration scope.
|
|
2087
2395
|
<div class="paragraph"><p>In each place, it may be specified at most once.</p></div>
|
2088
2396
|
</div>
|
2089
2397
|
<div class="sect3">
|
2090
|
-
<h4 id="_passenger_user_lt_group_name_gt">5.6.3. passenger_user <group name></h4>
|
2398
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_user_lt_group_name_gt" data-comment-topic="passenger-user-group-name--1fco4j7">5.6.3. passenger_user <group name></h4>
|
2091
2399
|
<div class="paragraph"><p>If <a href="#user_switching">user switching support</a> is enabled, then Phusion Passenger will
|
2092
2400
|
by default run the web application as the primary group of the owner of the file
|
2093
2401
|
<em>config/environment.rb</em> (for Rails apps) or <em>config.ru</em> (for Rack apps). This option
|
2094
2402
|
allows you to override that behavior and explicitly set a group to run the web application
|
2095
2403
|
as, regardless of the ownership of <em>environment.rb</em>/<em>config.ru</em>.</p></div>
|
2096
2404
|
<div class="paragraph"><p><em><group name></em> may also be set to the special value <em>!STARTUP_FILE!</em>, in which case
|
2097
|
-
the web application
|
2405
|
+
the web application’s group will be set to <em>environment.rb</em>/<em>config.ru</em>'s group.</p></div>
|
2098
2406
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2099
|
-
<div class="ulist"><ul>
|
2407
|
+
<div class="ulist"><ul>
|
2100
2408
|
<li>
|
2101
2409
|
<p>
|
2102
2410
|
In the <em>http</em> configuration block.
|
@@ -2121,7 +2429,7 @@ In an <em>if</em> configuration scope.
|
|
2121
2429
|
<div class="paragraph"><p>In each place, it may be specified at most once.</p></div>
|
2122
2430
|
</div>
|
2123
2431
|
<div class="sect3">
|
2124
|
-
<h4 id="PassengerDefaultUser">5.6.4. passenger_default_user <username></h4>
|
2432
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerDefaultUser" data-comment-topic="passenger-default-user-username--1h6cdmf">5.6.4. passenger_default_user <username></h4>
|
2125
2433
|
<div class="paragraph"><p>Phusion Passenger enables <a href="#user_switching">user switching support</a> by default.
|
2126
2434
|
This configuration option allows one to specify the user that applications must
|
2127
2435
|
run as, if user switching fails or is disabled.</p></div>
|
@@ -2129,7 +2437,7 @@ run as, if user switching fails or is disabled.</p></div>
|
|
2129
2437
|
The default value is <em>nobody</em>.</p></div>
|
2130
2438
|
</div>
|
2131
2439
|
<div class="sect3">
|
2132
|
-
<h4 id="PassengerDefaultGroup">5.6.5. Passenger_default_group <group name></h4>
|
2440
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerDefaultGroup" data-comment-topic="passenger-default-group-group-name--1qxn2qa">5.6.5. Passenger_default_group <group name></h4>
|
2133
2441
|
<div class="paragraph"><p>Phusion Passenger enables <a href="#user_switching">user switching support</a> by default.
|
2134
2442
|
This configuration option allows one to specify the group that applications must
|
2135
2443
|
run as, if user switching fails or is disabled.</p></div>
|
@@ -2138,7 +2446,7 @@ The default value is the primary group of the user specifified by
|
|
2138
2446
|
<a href="#PassengerDefaultUser">passenger_default_user</a>.</p></div>
|
2139
2447
|
</div>
|
2140
2448
|
<div class="sect3">
|
2141
|
-
<h4 id="_passenger_friendly_error_pages_lt_on_off_gt">5.6.6. passenger_friendly_error_pages <on|off></h4>
|
2449
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_friendly_error_pages_lt_on_off_gt" data-comment-topic="passenger-friendly-error-pages-on-off--27mews">5.6.6. passenger_friendly_error_pages <on|off></h4>
|
2142
2450
|
<div class="paragraph"><p>Phusion Passenger can display friendly error pages whenever an application fails
|
2143
2451
|
to start. This friendly error page presents the startup error message, some
|
2144
2452
|
suggestions for solving the problem, and a backtrace. This feature is very useful
|
@@ -2147,7 +2455,7 @@ but the page might reveal potentially sensitive information, depending on the
|
|
2147
2455
|
application. Experienced system administrators who are using Phusion Passenger
|
2148
2456
|
on serious production servers should consider turning this feature off.</p></div>
|
2149
2457
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2150
|
-
<div class="ulist"><ul>
|
2458
|
+
<div class="ulist"><ul>
|
2151
2459
|
<li>
|
2152
2460
|
<p>
|
2153
2461
|
In the <em>http</em> configuration block.
|
@@ -2173,13 +2481,13 @@ In an <em>if</em> configuration scope.
|
|
2173
2481
|
</div>
|
2174
2482
|
</div>
|
2175
2483
|
<div class="sect2">
|
2176
|
-
<h3 id="_resource_control_and_optimization_options">5.7. Resource control and optimization options</h3>
|
2484
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_resource_control_and_optimization_options" data-comment-topic="resource-control-and-optimization-options-xd7evs">5.7. Resource control and optimization options</h3>
|
2177
2485
|
<div class="sect3">
|
2178
|
-
<h4 id="PassengerMaxPoolSize">5.7.1. passenger_max_pool_size <integer></h4>
|
2486
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerMaxPoolSize" data-comment-topic="passenger-max-pool-size-integer--3jzefs">5.7.1. passenger_max_pool_size <integer></h4>
|
2179
2487
|
<div class="paragraph"><p>The maximum number of Ruby on Rails or Rack application instances that may
|
2180
2488
|
be simultaneously active. A larger number results in higher memory usage,
|
2181
2489
|
but improved ability to handle concurrent HTTP clients.</p></div>
|
2182
|
-
<div class="paragraph"><p>The optimal value depends on your system
|
2490
|
+
<div class="paragraph"><p>The optimal value depends on your system’s hardware and the server’s average
|
2183
2491
|
load. You should experiment with different values. But generally speaking,
|
2184
2492
|
the value should be at least equal to the number of CPUs (or CPU cores) that
|
2185
2493
|
you have. If your system has 2 GB of RAM, then we recommend a value of <em>30</em>.
|
@@ -2192,24 +2500,24 @@ hardware or getting more servers.)</p></div>
|
|
2192
2500
|
<div class="paragraph"><p>This option may only occur once, in the <em>http</em> configuration bock.
|
2193
2501
|
The default value is <em>6</em>.</p></div>
|
2194
2502
|
<div class="admonitionblock">
|
2195
|
-
<table><tr>
|
2503
|
+
<table><tr>
|
2196
2504
|
<td class="icon">
|
2197
|
-
<img src="./images/icons/tip.png" alt="Tip">
|
2505
|
+
<img src="./images/icons/tip.png" alt="Tip">
|
2198
2506
|
</td>
|
2199
2507
|
<td class="content">We strongly recommend you to <a href="#reducing_memory_usage">use Ruby Enterprise Edition</a>. This allows you to reduce the memory usage of your Ruby on Rails applications
|
2200
|
-
by about 33%. And it
|
2201
|
-
</tr></table>
|
2508
|
+
by about 33%. And it’s not hard to install.</td>
|
2509
|
+
</tr></table>
|
2202
2510
|
</div>
|
2203
2511
|
</div>
|
2204
2512
|
<div class="sect3">
|
2205
|
-
<h4 id="PassengerMinInstances">5.7.2. passenger_min_instances <integer></h4>
|
2513
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerMinInstances" data-comment-topic="passenger-min-instances-integer--uclykt">5.7.2. passenger_min_instances <integer></h4>
|
2206
2514
|
<div class="paragraph"><p>This specifies the minimum number of application instances that must be kept around
|
2207
2515
|
whenever Phusion Passenger cleans up idle instances. You should set this option to a
|
2208
2516
|
non-zero value if you want to avoid potentially long startup times after a website
|
2209
2517
|
has been idle for an extended period.</p></div>
|
2210
2518
|
<div class="paragraph"><p>Please note that this option does <strong>not</strong> pre-start application instances during Nginx
|
2211
2519
|
startup. It just makes sure that when the application is first accessed:</p></div>
|
2212
|
-
<div class="olist arabic"><ol class="arabic">
|
2520
|
+
<div class="olist arabic"><ol class="arabic">
|
2213
2521
|
<li>
|
2214
2522
|
<p>
|
2215
2523
|
at least the given number of instances will be spawned.
|
@@ -2240,18 +2548,19 @@ but <a href="#PassengerPreStart">passenger_pre_start</a> explains the rationale
|
|
2240
2548
|
passenger_min_instances 3;
|
2241
2549
|
}
|
2242
2550
|
}</pre>
|
2243
|
-
</div
|
2551
|
+
</div>
|
2552
|
+
</div>
|
2244
2553
|
<div class="paragraph"><p>When you start Nginx, there are 0 application instances for <em>foobar.com</em>. Things will
|
2245
2554
|
stay that way until someone visits <em>foobar.com</em>. Suppose that there is only 1 visitor.
|
2246
2555
|
1 application instance will be started immediately to serve the visitor, while 2 will
|
2247
2556
|
be spawned in the background. After 10 seconds, when the idle timeout has
|
2248
2557
|
been reached, these 3 application instances will not be cleaned up.</p></div>
|
2249
|
-
<div class="paragraph"><p>Now suppose that there
|
2558
|
+
<div class="paragraph"><p>Now suppose that there’s a sudden spike of traffic, and 100 users visit <em>foobar.com</em>
|
2250
2559
|
simultanously. Phusion Passenger will start 12 more application instances. After the idle
|
2251
2560
|
timeout of 10 seconds have passed, Phusion Passenger will clean up 12 application
|
2252
2561
|
instances, keeping 3 instances around.</p></div>
|
2253
2562
|
<div class="paragraph"><p>The passenger_min_instances option may occur in the following places:</p></div>
|
2254
|
-
<div class="ulist"><ul>
|
2563
|
+
<div class="ulist"><ul>
|
2255
2564
|
<li>
|
2256
2565
|
<p>
|
2257
2566
|
In the <em>http</em> configuration block.
|
@@ -2276,7 +2585,7 @@ In an <em>if</em> configuration scope.
|
|
2276
2585
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>1</em>.</p></div>
|
2277
2586
|
</div>
|
2278
2587
|
<div class="sect3">
|
2279
|
-
<h4 id="_passenger_max_instances_per_app_lt_integer_gt">5.7.3. passenger_max_instances_per_app <integer></h4>
|
2588
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_max_instances_per_app_lt_integer_gt" data-comment-topic="passenger-max-instances-per-app-integer--1p7q3cf">5.7.3. passenger_max_instances_per_app <integer></h4>
|
2280
2589
|
<div class="paragraph"><p>The maximum number of application instances that may be simultaneously active
|
2281
2590
|
for a single application. This helps to make sure that a single application
|
2282
2591
|
will not occupy all available slots in the application pool.</p></div>
|
@@ -2288,9 +2597,9 @@ will be enforced.</p></div>
|
|
2288
2597
|
The default value is <em>0</em>.</p></div>
|
2289
2598
|
</div>
|
2290
2599
|
<div class="sect3">
|
2291
|
-
<h4 id="PassengerPoolIdleTime">5.7.4. passenger_pool_idle_time <integer></h4>
|
2600
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerPoolIdleTime" data-comment-topic="passenger-pool-idle-time-integer--xcw65o">5.7.4. passenger_pool_idle_time <integer></h4>
|
2292
2601
|
<div class="paragraph"><p>The maximum number of seconds that an application instance may be idle. That is,
|
2293
|
-
if an application instance hasn
|
2602
|
+
if an application instance hasn’t received any traffic after the given number of
|
2294
2603
|
seconds, then it will be shutdown in order to conserve memory.</p></div>
|
2295
2604
|
<div class="paragraph"><p>Decreasing this value means that applications will have to be spawned
|
2296
2605
|
more often. Since spawning is a relatively slow operation, some visitors may
|
@@ -2301,16 +2610,16 @@ Rails/Rack web page. We recommend a value of <span class="monospaced">2 * x</spa
|
|
2301
2610
|
number of seconds that a visitor spends on a single Rails/Rack web page. But your
|
2302
2611
|
mileage may vary.</p></div>
|
2303
2612
|
<div class="paragraph"><p>When this value is set to <em>0</em>, application instances will not be shutdown unless
|
2304
|
-
it
|
2613
|
+
it’s really necessary, i.e. when Phusion Passenger is out of worker processes
|
2305
2614
|
for a given application and one of the inactive application instances needs to
|
2306
2615
|
make place for another application instance. Setting the value to 0 is
|
2307
|
-
recommended if you
|
2616
|
+
recommended if you’re on a non-shared host that’s only running a few
|
2308
2617
|
applications, each which must be available at all times.</p></div>
|
2309
2618
|
<div class="paragraph"><p>This option may only occur once, in the <em>http</em> configuration block.
|
2310
2619
|
The default value is <em>300</em>.</p></div>
|
2311
2620
|
</div>
|
2312
2621
|
<div class="sect3">
|
2313
|
-
<h4 id="PassengerMaxRequests">5.7.5. passenger_max_requests <integer></h4>
|
2622
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerMaxRequests" data-comment-topic="passenger-max-requests-integer--sgzint">5.7.5. passenger_max_requests <integer></h4>
|
2314
2623
|
<div class="paragraph"><p>The maximum number of requests an application instance will process. After
|
2315
2624
|
serving that many requests, the application instance will be shut down and
|
2316
2625
|
Phusion Passenger will restart it. A value of 0 means that there is no maximum:
|
@@ -2320,7 +2629,7 @@ reached.</p></div>
|
|
2320
2629
|
it down after a certain number of requests, all of its memory is guaranteed
|
2321
2630
|
to be freed by the operating system.</p></div>
|
2322
2631
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2323
|
-
<div class="ulist"><ul>
|
2632
|
+
<div class="ulist"><ul>
|
2324
2633
|
<li>
|
2325
2634
|
<p>
|
2326
2635
|
In the <em>http</em> configuration block.
|
@@ -2344,9 +2653,9 @@ In an <em>if</em> configuration scope.
|
|
2344
2653
|
</ul></div>
|
2345
2654
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>0</em>.</p></div>
|
2346
2655
|
<div class="admonitionblock">
|
2347
|
-
<table><tr>
|
2656
|
+
<table><tr>
|
2348
2657
|
<td class="icon">
|
2349
|
-
<img src="./images/icons/caution.png" alt="Caution">
|
2658
|
+
<img src="./images/icons/caution.png" alt="Caution">
|
2350
2659
|
</td>
|
2351
2660
|
<td class="content">
|
2352
2661
|
<div class="paragraph"><p>The <a href="#PassengerMaxRequests">passenger_max_requests</a> directive should be considered
|
@@ -2354,25 +2663,25 @@ as a workaround for misbehaving applications. It is advised that you fix the
|
|
2354
2663
|
problem in your application rather than relying on these directives as a
|
2355
2664
|
measure to avoid memory leaks.</p></div>
|
2356
2665
|
</td>
|
2357
|
-
</tr></table>
|
2666
|
+
</tr></table>
|
2358
2667
|
</div>
|
2359
2668
|
</div>
|
2360
2669
|
<div class="sect3">
|
2361
|
-
<h4 id="PassengerPreStart">5.7.6. passenger_pre_start <url></h4>
|
2670
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="PassengerPreStart" data-comment-topic="passenger-pre-start-url--qeevln">5.7.6. passenger_pre_start <url></h4>
|
2362
2671
|
<div class="paragraph"><p>By default, Phusion Passenger does not start any application instances until said
|
2363
2672
|
web application is first accessed. The result is that the first visitor of said
|
2364
2673
|
web application might experience a small delay as Phusion Passenger is starting
|
2365
2674
|
the web application on demand. If that is undesirable, then this directive can be
|
2366
2675
|
used to pre-started application instances during Nginx startup.</p></div>
|
2367
2676
|
<div class="paragraph"><p>A few things to be careful of:</p></div>
|
2368
|
-
<div class="ulist"><ul>
|
2677
|
+
<div class="ulist"><ul>
|
2369
2678
|
<li>
|
2370
2679
|
<p>
|
2371
2680
|
This directive accepts the <strong>URL</strong> of the web application you want to pre-start,
|
2372
2681
|
not a on/off value! This might seem a bit weird, but read on for rationale. As
|
2373
2682
|
for the specifics of the URL:
|
2374
2683
|
</p>
|
2375
|
-
<div class="ulist"><ul>
|
2684
|
+
<div class="ulist"><ul>
|
2376
2685
|
<li>
|
2377
2686
|
<p>
|
2378
2687
|
The domain part of the URL must be equal to the value of the <em>server_name</em>
|
@@ -2382,7 +2691,7 @@ The domain part of the URL must be equal to the value of the <em>server_name</em
|
|
2382
2691
|
<li>
|
2383
2692
|
<p>
|
2384
2693
|
Unless the web application is deployed on port 80, the URL should contain
|
2385
|
-
the web application
|
2694
|
+
the web application’s port number too.
|
2386
2695
|
</p>
|
2387
2696
|
</li>
|
2388
2697
|
<li>
|
@@ -2422,7 +2731,8 @@ server {
|
|
2422
2731
|
root /webapps/bar/public;
|
2423
2732
|
passenger_enabled on;
|
2424
2733
|
}</pre>
|
2425
|
-
</div
|
2734
|
+
</div>
|
2735
|
+
</div>
|
2426
2736
|
<div class="paragraph"><p>You want both of them to be pre-started during Nginx startup. The URL for
|
2427
2737
|
foo.com is <em>http://foo.com/</em> (or, equivalently, <em>http://foo.com:80/</em>) and
|
2428
2738
|
the URL for bar.com is <em>http://bar.com:3500/</em>. So we add two passenger_pre_start
|
@@ -2445,7 +2755,8 @@ server {
|
|
2445
2755
|
|
2446
2756
|
passenger_pre_start http://foo.com/; # <--- added
|
2447
2757
|
passenger_pre_start http://bar.com:3500/; # <--- added</pre>
|
2448
|
-
</div
|
2758
|
+
</div>
|
2759
|
+
</div>
|
2449
2760
|
</div>
|
2450
2761
|
<div class="sect4">
|
2451
2762
|
<h5 id="_example_2_pre_starting_apps_that_are_deployed_in_sub_uris">Example 2: pre-starting apps that are deployed in sub-URIs</h5>
|
@@ -2458,7 +2769,8 @@ passenger_pre_start http://bar.com:3500/; # <--- added</pre>
|
|
2458
2769
|
root /webapps/wordpress;
|
2459
2770
|
rails_base_uri /store;
|
2460
2771
|
}</pre>
|
2461
|
-
</div
|
2772
|
+
</div>
|
2773
|
+
</div>
|
2462
2774
|
<div class="paragraph"><p>Then specify the <em>server_name</em> value followed by the sub-URI, like this:</p></div>
|
2463
2775
|
<div class="listingblock">
|
2464
2776
|
<div class="content monospaced">
|
@@ -2470,13 +2782,15 @@ passenger_pre_start http://bar.com:3500/; # <--- added</pre>
|
|
2470
2782
|
}
|
2471
2783
|
|
2472
2784
|
passenger_pre_start http://myblog.com/store; # <----- added</pre>
|
2473
|
-
</div
|
2474
|
-
|
2475
|
-
The
|
2785
|
+
</div>
|
2786
|
+
</div>
|
2787
|
+
<div class="paragraph"><p>The sub-URI <strong>must</strong> be included; if you don’t then the directive will have no effect.
|
2788
|
+
The following example is wrong and won’t pre-start the store web application:</p></div>
|
2476
2789
|
<div class="listingblock">
|
2477
2790
|
<div class="content monospaced">
|
2478
2791
|
<pre>passenger_pre_start http://myblog.com/; # <----- WRONG! Missing "/store" part.</pre>
|
2479
|
-
</div
|
2792
|
+
</div>
|
2793
|
+
</div>
|
2480
2794
|
</div>
|
2481
2795
|
<div class="sect4">
|
2482
2796
|
<h5 id="_example_3_combining_with_passenger_min_instances">Example 3: combining with passenger_min_instances</h5>
|
@@ -2484,7 +2798,7 @@ The following example is wrong and won’t pre-start the store web applicati
|
|
2484
2798
|
also subject to the idle timeout rules as specified by
|
2485
2799
|
<a href="#PassengerPoolIdleTime">passenger_pool_idle_time</a>! That means that by default,
|
2486
2800
|
the pre-started application instances for foo.com are bar.com are shut down
|
2487
|
-
after a few minutes of inactivity. If you don
|
2801
|
+
after a few minutes of inactivity. If you don’t want that to happen, then
|
2488
2802
|
you should combine passenger_pre_start with
|
2489
2803
|
<a href="#PassengerMinInstances">passenger_min_instances</a>, like this:</p></div>
|
2490
2804
|
<div class="listingblock">
|
@@ -2507,17 +2821,18 @@ server {
|
|
2507
2821
|
|
2508
2822
|
passenger_pre_start http://foo.com/;
|
2509
2823
|
passenger_pre_start http://bar.com:3500/;</pre>
|
2510
|
-
</div
|
2824
|
+
</div>
|
2825
|
+
</div>
|
2511
2826
|
</div>
|
2512
2827
|
<div class="sect4">
|
2513
2828
|
<h5 id="_so_why_a_url_why_not_just_an_on_off_flag">So why a URL? Why not just an on/off flag?</h5>
|
2514
2829
|
<div class="paragraph"><p>A directive that accepts a simple on/off flag is definitely more intuitive,
|
2515
|
-
but due technical difficulties w.r.t. the way Nginx works, it
|
2830
|
+
but due technical difficulties w.r.t. the way Nginx works, it’s very hard
|
2516
2831
|
to implement it like that:</p></div>
|
2517
2832
|
<div class="paragraph"><p>It is very hard to obtain a full list of web applications defined in the
|
2518
|
-
Nginx configuration file(s). In other words, it
|
2833
|
+
Nginx configuration file(s). In other words, it’s hard for Phusion Passenger
|
2519
2834
|
to know which web applications are deployed on Nginx until a web application
|
2520
|
-
is first accessed, and without such a list Phusion Passenger wouldn
|
2835
|
+
is first accessed, and without such a list Phusion Passenger wouldn’t know
|
2521
2836
|
which web applications to pre-start. So as a compromise, we made it accept a
|
2522
2837
|
URL.</p></div>
|
2523
2838
|
</div>
|
@@ -2535,7 +2850,8 @@ port 3500):</p></div>
|
|
2535
2850
|
<pre>HEAD / HTTP/1.1
|
2536
2851
|
Host: bar.com
|
2537
2852
|
Connection: close</pre>
|
2538
|
-
</div
|
2853
|
+
</div>
|
2854
|
+
</div>
|
2539
2855
|
<div class="paragraph"><p>Similarly, for example 2, Phusion Passenger will send the following HTTP request
|
2540
2856
|
to 127.0.0.1 port 80:</p></div>
|
2541
2857
|
<div class="listingblock">
|
@@ -2543,19 +2859,20 @@ to 127.0.0.1 port 80:</p></div>
|
|
2543
2859
|
<pre>HEAD /store HTTP/1.1
|
2544
2860
|
Host: myblog.com
|
2545
2861
|
Connection: close</pre>
|
2546
|
-
</div
|
2862
|
+
</div>
|
2863
|
+
</div>
|
2547
2864
|
</div>
|
2548
2865
|
<div class="sect4">
|
2549
2866
|
<h5 id="_do_i_need_to_edit_etc_hosts_and_point_the_domain_in_the_url_to_127_0_0_1">Do I need to edit /etc/hosts and point the domain in the URL to 127.0.0.1?</h5>
|
2550
2867
|
<div class="paragraph"><p>No. See previous subsection.</p></div>
|
2551
2868
|
</div>
|
2552
2869
|
<div class="sect4">
|
2553
|
-
<h5 id="_my_web_application_consists_of_multiple_web_servers_what_url_do_i_need_to_specify_and_in_which_web_server_8217_s_nginx_config_file">My web application consists of multiple web servers. What URL do I need to specify, and in which web server
|
2554
|
-
<div class="paragraph"><p>Put the web application
|
2870
|
+
<h5 id="_my_web_application_consists_of_multiple_web_servers_what_url_do_i_need_to_specify_and_in_which_web_server_8217_s_nginx_config_file">My web application consists of multiple web servers. What URL do I need to specify, and in which web server’s Nginx config file?</h5>
|
2871
|
+
<div class="paragraph"><p>Put the web application’s <em>server_name</em> value and the server block’s
|
2555
2872
|
port in the URL, and put
|
2556
2873
|
passenger_pre_start on all machines that you want to pre-start the web application
|
2557
2874
|
on. The simulated web request is always sent to 127.0.0.1, with the domain name
|
2558
|
-
in the URL as value for the <em>Host</em> HTTP header, so you don
|
2875
|
+
in the URL as value for the <em>Host</em> HTTP header, so you don’t need to worry about
|
2559
2876
|
the request ending up at a different web server in the cluster.</p></div>
|
2560
2877
|
</div>
|
2561
2878
|
<div class="sect4">
|
@@ -2565,14 +2882,14 @@ the request ending up at a different web server in the cluster.</p></div>
|
|
2565
2882
|
</div>
|
2566
2883
|
</div>
|
2567
2884
|
<div class="sect2">
|
2568
|
-
<h3 id="_logging_and_debugging_options">5.8. Logging and debugging options</h3>
|
2885
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_logging_and_debugging_options" data-comment-topic="logging-and-debugging-options-14e91ni">5.8. Logging and debugging options</h3>
|
2569
2886
|
<div class="sect3">
|
2570
|
-
<h4 id="_passenger_log_level_lt_integer_gt">5.8.1. passenger_log_level <integer></h4>
|
2887
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_log_level_lt_integer_gt" data-comment-topic="passenger-log-level-integer--17snhon">5.8.1. passenger_log_level <integer></h4>
|
2571
2888
|
<div class="paragraph"><p>This option allows one to specify how much information Phusion Passenger should
|
2572
2889
|
write to the Nginx error log file. A higher log level value means that more
|
2573
2890
|
information will be logged.</p></div>
|
2574
2891
|
<div class="paragraph"><p>Possible values are:</p></div>
|
2575
|
-
<div class="ulist"><ul>
|
2892
|
+
<div class="ulist"><ul>
|
2576
2893
|
<li>
|
2577
2894
|
<p>
|
2578
2895
|
<em>0</em>: Show only errors and warnings.
|
@@ -2600,7 +2917,7 @@ information will be logged.</p></div>
|
|
2600
2917
|
The default is <em>0</em>.</p></div>
|
2601
2918
|
</div>
|
2602
2919
|
<div class="sect3">
|
2603
|
-
<h4 id="_passenger_debug_log_file_lt_filename_gt">5.8.2. passenger_debug_log_file <filename></h4>
|
2920
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_passenger_debug_log_file_lt_filename_gt" data-comment-topic="passenger-debug-log-file-filename--21ubaj">5.8.2. passenger_debug_log_file <filename></h4>
|
2604
2921
|
<div class="paragraph"><p>By default Phusion Passenger debugging and error messages are written to the global
|
2605
2922
|
web server error log. This option allows one to specify the file that debugging and
|
2606
2923
|
error messages should be written to instead.</p></div>
|
@@ -2608,12 +2925,12 @@ error messages should be written to instead.</p></div>
|
|
2608
2925
|
</div>
|
2609
2926
|
</div>
|
2610
2927
|
<div class="sect2">
|
2611
|
-
<h3 id="_ruby_on_rails_specific_options">5.9. Ruby on Rails-specific options</h3>
|
2928
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_ruby_on_rails_specific_options" data-comment-topic="ruby-on-rails-specific-options-12vfokt">5.9. Ruby on Rails-specific options</h3>
|
2612
2929
|
<div class="sect3">
|
2613
|
-
<h4 id="RailsEnv">5.9.1. rails_env <string></h4>
|
2930
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="RailsEnv" data-comment-topic="rails-env-string--jlh7v9">5.9.1. rails_env <string></h4>
|
2614
2931
|
<div class="paragraph"><p>This option allows one to specify the default <span class="monospaced">RAILS_ENV</span> value.</p></div>
|
2615
2932
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2616
|
-
<div class="ulist"><ul>
|
2933
|
+
<div class="ulist"><ul>
|
2617
2934
|
<li>
|
2618
2935
|
<p>
|
2619
2936
|
In the <em>http</em> configuration block.
|
@@ -2638,21 +2955,21 @@ In an <em>if</em> configuration scope.
|
|
2638
2955
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>production</em>.</p></div>
|
2639
2956
|
</div>
|
2640
2957
|
<div class="sect3">
|
2641
|
-
<h4 id="_rails_framework_spawner_idle_time_lt_integer_gt">5.9.2. rails_framework_spawner_idle_time <integer></h4>
|
2958
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_rails_framework_spawner_idle_time_lt_integer_gt" data-comment-topic="rails-framework-spawner-idle-time-integer--q5ljd5">5.9.2. rails_framework_spawner_idle_time <integer></h4>
|
2642
2959
|
<div class="paragraph"><p>The FrameworkSpawner server (explained in <a href="#spawning_methods_explained">Spawning methods explained</a>) has an idle timeout, just like the backend processes spawned by
|
2643
|
-
Phusion Passenger do. That is, it will automatically shutdown if it hasn
|
2960
|
+
Phusion Passenger do. That is, it will automatically shutdown if it hasn’t done
|
2644
2961
|
anything for a given period.</p></div>
|
2645
|
-
<div class="paragraph"><p>This option allows you to set the FrameworkSpawner server
|
2962
|
+
<div class="paragraph"><p>This option allows you to set the FrameworkSpawner server’s idle timeout, in
|
2646
2963
|
seconds. A value of <em>0</em> means that it should never idle timeout.</p></div>
|
2647
2964
|
<div class="paragraph"><p>Setting a higher value will mean that the FrameworkSpawner server is kept around
|
2648
2965
|
longer, which may slightly increase memory usage. But as long as the
|
2649
2966
|
FrameworkSpawner server is running, the time to spawn a Ruby on Rails backend
|
2650
2967
|
process only takes about 40% of the time that is normally needed, assuming that
|
2651
|
-
you
|
2968
|
+
you’re using the <em>smart</em> <a href="#RailsSpawnMethod">spawning method</a>. So if your
|
2652
2969
|
system has enough memory, is it recommended that you set this option to a high
|
2653
2970
|
value or to <em>0</em>.</p></div>
|
2654
2971
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2655
|
-
<div class="ulist"><ul>
|
2972
|
+
<div class="ulist"><ul>
|
2656
2973
|
<li>
|
2657
2974
|
<p>
|
2658
2975
|
In the <em>http</em> configuration block.
|
@@ -2677,21 +2994,21 @@ In an <em>if</em> configuration scope.
|
|
2677
2994
|
<div class="paragraph"><p>In each place, it may be specified at most once. The default value is <em>1800</em> (30 minutes).</p></div>
|
2678
2995
|
</div>
|
2679
2996
|
<div class="sect3">
|
2680
|
-
<h4 id="_rails_app_spawner_idle_time_lt_integer_gt">5.9.3. rails_app_spawner_idle_time <integer></h4>
|
2997
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_rails_app_spawner_idle_time_lt_integer_gt" data-comment-topic="rails-app-spawner-idle-time-integer--1xjqe4b">5.9.3. rails_app_spawner_idle_time <integer></h4>
|
2681
2998
|
<div class="paragraph"><p>The ApplicationSpawner server (explained in <a href="#spawning_methods_explained">Spawning methods explained</a>) has an idle timeout, just like the backend processes spawned by
|
2682
|
-
Phusion Passenger do. That is, it will automatically shutdown if it hasn
|
2999
|
+
Phusion Passenger do. That is, it will automatically shutdown if it hasn’t done
|
2683
3000
|
anything for a given period.</p></div>
|
2684
|
-
<div class="paragraph"><p>This option allows you to set the ApplicationSpawner server
|
3001
|
+
<div class="paragraph"><p>This option allows you to set the ApplicationSpawner server’s idle timeout, in
|
2685
3002
|
seconds. A value of <em>0</em> means that it should never idle timeout.</p></div>
|
2686
3003
|
<div class="paragraph"><p>Setting a higher value will mean that the ApplicationSpawner server is kept around
|
2687
3004
|
longer, which may slightly increase memory usage. But as long as the
|
2688
3005
|
ApplicationSpawner server is running, the time to spawn a Ruby on Rails backend
|
2689
3006
|
process only takes about 10% of the time that is normally needed, assuming that
|
2690
|
-
you
|
3007
|
+
you’re using the <em>smart</em> or <em>smart-lv2</em> <a href="#RailsSpawnMethod">spawning method</a>. So if your
|
2691
3008
|
system has enough memory, is it recommended that you set this option to a high
|
2692
3009
|
value or to <em>0</em>.</p></div>
|
2693
3010
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2694
|
-
<div class="ulist"><ul>
|
3011
|
+
<div class="ulist"><ul>
|
2695
3012
|
<li>
|
2696
3013
|
<p>
|
2697
3014
|
In the <em>http</em> configuration block.
|
@@ -2717,12 +3034,12 @@ In an <em>if</em> configuration scope.
|
|
2717
3034
|
</div>
|
2718
3035
|
</div>
|
2719
3036
|
<div class="sect2">
|
2720
|
-
<h3 id="_rack_specific_options">5.10. Rack-specific options</h3>
|
3037
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_rack_specific_options" data-comment-topic="rack-specific-options-13yvdxs">5.10. Rack-specific options</h3>
|
2721
3038
|
<div class="sect3">
|
2722
|
-
<h4 id="RackEnv">5.10.1. rack_env <string></h4>
|
3039
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="RackEnv" data-comment-topic="rack-env-string--tqmrt0">5.10.1. rack_env <string></h4>
|
2723
3040
|
<div class="paragraph"><p>This option allows one to specify the default <span class="monospaced">RACK_ENV</span> value.</p></div>
|
2724
3041
|
<div class="paragraph"><p>This option may occur in the following places:</p></div>
|
2725
|
-
<div class="ulist"><ul>
|
3042
|
+
<div class="ulist"><ul>
|
2726
3043
|
<li>
|
2727
3044
|
<p>
|
2728
3045
|
In the <em>http</em> configuration block.
|
@@ -2748,31 +3065,31 @@ In an <em>if</em> configuration scope.
|
|
2748
3065
|
</div>
|
2749
3066
|
</div>
|
2750
3067
|
<div class="sect2">
|
2751
|
-
<h3 id="_deprecated_options">5.11. Deprecated options</h3>
|
3068
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_deprecated_options" data-comment-topic="deprecated-options-1dtzo0g">5.11. Deprecated options</h3>
|
2752
3069
|
<div class="paragraph"><p>The following options have been deprecated, but are still supported for backwards
|
2753
3070
|
compatibility reasons.</p></div>
|
2754
3071
|
<div class="sect3">
|
2755
|
-
<h4 id="_rails_spawn_method">5.11.1. rails_spawn_method</h4>
|
3072
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_rails_spawn_method" data-comment-topic="rails-spawn-method-17vdnpt">5.11.1. rails_spawn_method</h4>
|
2756
3073
|
<div class="paragraph"><p>Deprecated in favor of <a href="#PassengerSpawnMethod">passenger_spawn_method</a>.</p></div>
|
2757
3074
|
</div>
|
2758
3075
|
</div>
|
2759
3076
|
</div>
|
2760
3077
|
</div>
|
2761
3078
|
<div class="sect1">
|
2762
|
-
<h2 id="_analysis_and_system_maintenance">6. Analysis and system maintenance</h2>
|
3079
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_analysis_and_system_maintenance" data-comment-topic="analysis-and-system-maintenance-1nnlnj8">6. Analysis and system maintenance</h2>
|
2763
3080
|
<div class="sectionbody">
|
2764
3081
|
<div class="paragraph"><p>Phusion Passenger provides a set of tools, which are useful for system analysis,
|
2765
3082
|
maintenance and troubleshooting.</p></div>
|
2766
3083
|
<div class="sect2">
|
2767
|
-
<h3 id="_inspecting_memory_usage">6.1. Inspecting memory usage</h3>
|
3084
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_inspecting_memory_usage" data-comment-topic="inspecting-memory-usage-1k6y8v0">6.1. Inspecting memory usage</h3>
|
2768
3085
|
<div class="paragraph"><p>Process inspection tools such as <span class="monospaced">ps</span> and <span class="monospaced">top</span> are useful, but they
|
2769
3086
|
<a href="http://groups.google.com/group/phusion-passenger/msg/1fd1c233456d3180">rarely show the correct memory usage</a>.
|
2770
3087
|
The real memory usage is usually lower than what <span class="monospaced">ps</span> and <span class="monospaced">top</span> report.</p></div>
|
2771
3088
|
<div class="paragraph"><p>There are many technical reasons why this is so, but an explanation is beyond
|
2772
3089
|
the scope of this Users Guide. We kindly refer the interested reader to
|
2773
3090
|
operating systems literature about <em>virtual memory</em> and <em>copy-on-write</em>.</p></div>
|
2774
|
-
<div class="paragraph"><p>The tool <span class="monospaced">passenger-memory-stats</span> allows one to easily analyze Phusion Passenger
|
2775
|
-
and Apache
|
3091
|
+
<div class="paragraph"><p>The tool <span class="monospaced">passenger-memory-stats</span> allows one to easily analyze Phusion Passenger’s
|
3092
|
+
and Apache’s real memory usage. For example:</p></div>
|
2776
3093
|
<div class="listingblock">
|
2777
3094
|
<div class="content monospaced">
|
2778
3095
|
<pre>[bash@localhost root]# passenger-memory-stats
|
@@ -2799,25 +3116,26 @@ PID Threads VMSize Private Name
|
|
2799
3116
|
23793 1 26.9 MB 17.1 MB Rails: /var/www/projects/app1-foobar
|
2800
3117
|
### Processes: 4
|
2801
3118
|
### Total private dirty RSS: 27.76 M</pre>
|
2802
|
-
</div
|
3119
|
+
</div>
|
3120
|
+
</div>
|
2803
3121
|
<div class="paragraph"><p>The <em>Private</em> or <em>private dirty RSS</em> field shows the <strong>real</strong> memory usage of processes. Here,
|
2804
3122
|
we see that all the Apache worker processes only take less than 1 MB memory each.
|
2805
3123
|
This is a lot less than the 50 MB-ish memory usage as shown in the <em>VMSize</em> column
|
2806
3124
|
(which is what a lot of people think is the real memory usage, but is actually not).</p></div>
|
2807
3125
|
<div class="admonitionblock">
|
2808
|
-
<table><tr>
|
3126
|
+
<table><tr>
|
2809
3127
|
<td class="icon">
|
2810
|
-
<img src="./images/icons/note.png" alt="Note">
|
3128
|
+
<img src="./images/icons/note.png" alt="Note">
|
2811
3129
|
</td>
|
2812
3130
|
<td class="content">Private dirty RSS reporting only works on Linux. Unfortunately other operating systems
|
2813
|
-
don
|
3131
|
+
don’t provide facilities for determining processes' private dirty RSS. On non-Linux systems,
|
2814
3132
|
the Resident Set Size is reported instead.</td>
|
2815
|
-
</tr></table>
|
3133
|
+
</tr></table>
|
2816
3134
|
</div>
|
2817
3135
|
</div>
|
2818
3136
|
<div class="sect2">
|
2819
|
-
<h3 id="_inspecting_phusion_passenger_8217_s_internal_status">6.2. Inspecting Phusion Passenger
|
2820
|
-
<div class="paragraph"><p>One can inspect Phusion Passenger
|
3137
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_inspecting_phusion_passenger_8217_s_internal_status" data-comment-topic="inspecting-phusion-passenger-s-internal-status-v36wbc">6.2. Inspecting Phusion Passenger’s internal status</h3>
|
3138
|
+
<div class="paragraph"><p>One can inspect Phusion Passenger’s internal status with the tool <span class="monospaced">passenger-status</span>.
|
2821
3139
|
This tool must typically be run as root. For example:</p></div>
|
2822
3140
|
<div class="listingblock">
|
2823
3141
|
<div class="content monospaced">
|
@@ -2831,9 +3149,10 @@ inactive = 1
|
|
2831
3149
|
----------- Domains -----------
|
2832
3150
|
/var/www/projects/app1-foobar:
|
2833
3151
|
PID: 9617 Sessions: 0 Processed: 7 Uptime: 2m 23s</pre>
|
2834
|
-
</div
|
3152
|
+
</div>
|
3153
|
+
</div>
|
2835
3154
|
<div class="paragraph"><p>The <em>general information</em> section shows the following information:</p></div>
|
2836
|
-
<div class="dlist"><dl>
|
3155
|
+
<div class="dlist"><dl>
|
2837
3156
|
<dt class="hdlist1">
|
2838
3157
|
max
|
2839
3158
|
</dt>
|
@@ -2877,7 +3196,7 @@ time). The value of <em>inactive</em> equals <span class="monospaced">count - ac
|
|
2877
3196
|
</dl></div>
|
2878
3197
|
<div class="paragraph"><p>The <em>domains</em> section shows, for each application directory, information about running
|
2879
3198
|
application instances:</p></div>
|
2880
|
-
<div class="dlist"><dl>
|
3199
|
+
<div class="dlist"><dl>
|
2881
3200
|
<dt class="hdlist1">
|
2882
3201
|
Sessions
|
2883
3202
|
</dt>
|
@@ -2892,7 +3211,7 @@ Processed
|
|
2892
3211
|
</dt>
|
2893
3212
|
<dd>
|
2894
3213
|
<p>
|
2895
|
-
Indicates how many requests the instance has served until now. <strong>Tip:</strong> it
|
3214
|
+
Indicates how many requests the instance has served until now. <strong>Tip:</strong> it’s
|
2896
3215
|
possible to limit this number with the <a href="#PassengerMaxRequests">PassengerMaxRequests</a>
|
2897
3216
|
configuration directive.
|
2898
3217
|
</p>
|
@@ -2915,7 +3234,8 @@ normal:</p></div>
|
|
2915
3234
|
PID: 4268 Sessions: 0 Processed: 5 Uptime: 4m 52s
|
2916
3235
|
PID: 4265 Sessions: 1 Processed: 6 Uptime: 5m 38s
|
2917
3236
|
PID: 4275 Sessions: 1 Processed: 7 Uptime: 3m 14s</pre>
|
2918
|
-
</div
|
3237
|
+
</div>
|
3238
|
+
</div>
|
2919
3239
|
<div class="paragraph"><p>But if you see a "spike", i.e. an application instance has an unusually high number of
|
2920
3240
|
sessions compared to the others, then there might be a problem:</p></div>
|
2921
3241
|
<div class="listingblock">
|
@@ -2926,9 +3246,10 @@ sessions compared to the others, then there might be a problem:</p></div>
|
|
2926
3246
|
PID: 4275 Sessions: 1 | Processed: 7 Uptime: 3m 14s
|
2927
3247
|
|
|
2928
3248
|
+---- "spike"</pre>
|
2929
|
-
</div
|
3249
|
+
</div>
|
3250
|
+
</div>
|
2930
3251
|
<div class="paragraph"><p>Possible reasons why spikes can occur:</p></div>
|
2931
|
-
<div class="olist arabic"><ol class="arabic">
|
3252
|
+
<div class="olist arabic"><ol class="arabic">
|
2932
3253
|
<li>
|
2933
3254
|
<p>
|
2934
3255
|
Your application is busy processing a request that takes a very long time.
|
@@ -2945,39 +3266,39 @@ Your application is frozen, i.e. has stopped responding. See
|
|
2945
3266
|
</ol></div>
|
2946
3267
|
</div>
|
2947
3268
|
<div class="sect2">
|
2948
|
-
<h3 id="debugging_frozen">6.3. Debugging frozen applications</h3>
|
3269
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="debugging_frozen" data-comment-topic="debugging-frozen-applications-qoctl8">6.3. Debugging frozen applications</h3>
|
2949
3270
|
<div class="paragraph"><p>If one of your application instances is frozen (stopped responding), then you
|
2950
3271
|
can figure out where it is frozen by killing it with <em>SIGABRT</em>. This will cause the
|
2951
3272
|
application to raise an exception, with a backtrace.</p></div>
|
2952
3273
|
<div class="paragraph"><p>The exception (with full backtrace information) is normally logged into the Apache
|
2953
3274
|
error log. But if your application or if its web framework has its own exception logging
|
2954
|
-
routines, then exceptions might be logged into the application
|
3275
|
+
routines, then exceptions might be logged into the application’s log files instead.
|
2955
3276
|
This is the case with Ruby on Rails. So if you kill a Ruby on Rails application with
|
2956
|
-
<em>SIGABRT</em>, please check the application
|
2957
|
-
running it in a <em>production</em> environment). If you don
|
3277
|
+
<em>SIGABRT</em>, please check the application’s <em>production.log</em> first (assuming that you’re
|
3278
|
+
running it in a <em>production</em> environment). If you don’t see a backtrace there, check
|
2958
3279
|
the Apache error log.</p></div>
|
2959
3280
|
<div class="admonitionblock">
|
2960
|
-
<table><tr>
|
3281
|
+
<table><tr>
|
2961
3282
|
<td class="icon">
|
2962
|
-
<img src="./images/icons/note.png" alt="Note">
|
3283
|
+
<img src="./images/icons/note.png" alt="Note">
|
2963
3284
|
</td>
|
2964
3285
|
<td class="content">It is safe to kill application instances, even in live environments. Phusion Passenger
|
2965
3286
|
will restart killed application instances, as if nothing bad happened.</td>
|
2966
|
-
</tr></table>
|
3287
|
+
</tr></table>
|
2967
3288
|
</div>
|
2968
3289
|
</div>
|
2969
3290
|
<div class="sect2">
|
2970
|
-
<h3 id="_accessing_individual_application_processes">6.4. Accessing individual application processes</h3>
|
3291
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_accessing_individual_application_processes" data-comment-topic="accessing-individual-application-processes-1qe4fqk">6.4. Accessing individual application processes</h3>
|
2971
3292
|
<div class="paragraph"><p>When a request is sent to the web server, Phusion Passenger will automatically forward
|
2972
3293
|
the request to the most suitable application process, but sometimes it is desirable to
|
2973
3294
|
be able to directly access the individual application processes. Use cases include, but
|
2974
3295
|
are not limited to:</p></div>
|
2975
|
-
<div class="ulist"><ul>
|
3296
|
+
<div class="ulist"><ul>
|
2976
3297
|
<li>
|
2977
3298
|
<p>
|
2978
3299
|
One wants to debug a memory leak or memory bloat problem that only seems to appear on
|
2979
3300
|
certain URIs. One can send a request to a specific process to see whether that request
|
2980
|
-
causes the process
|
3301
|
+
causes the process’s memory usage to rise.
|
2981
3302
|
</p>
|
2982
3303
|
</li>
|
2983
3304
|
<li>
|
@@ -2998,7 +3319,7 @@ HTTP tools like <em>curl</em>. The exact addresses can be obtained with the comm
|
|
2998
3319
|
number is dynamically assigned. As a security measure, the sockets are also protected
|
2999
3320
|
with a process-specific random password, which you can see in the
|
3000
3321
|
<span class="monospaced">passenger-status --verbose</span> output. This password must be sent through the
|
3001
|
-
|
3322
|
+
“X-Passenger-Connect-Password” HTTP header.</p></div>
|
3002
3323
|
<div class="paragraph"><p>Example:</p></div>
|
3003
3324
|
<div class="listingblock">
|
3004
3325
|
<div class="content monospaced">
|
@@ -3019,7 +3340,8 @@ Waiting on global queue: 0
|
|
3019
3340
|
* PID: 24250 Sessions: 0 Processed: 4 Uptime: 1s
|
3020
3341
|
URL : http://127.0.0.1:57933
|
3021
3342
|
Password: _RGXlQ9EGDGJKLevQ_qflUtF1KmxEo2UiRzMwIE1sBY</pre>
|
3022
|
-
</div
|
3343
|
+
</div>
|
3344
|
+
</div>
|
3023
3345
|
<div class="paragraph"><p>Here we see that the web application <em>rack.test</em> has two processes.
|
3024
3346
|
Process 24235 is accessible via <a href="http://127.0.0.1:58122">http://127.0.0.1:58122</a>, and
|
3025
3347
|
process 24250 is accessible via <a href="http://127.0.0.1:57933">http://127.0.0.1:57933</a>.</p></div>
|
@@ -3028,31 +3350,32 @@ through the <em>X-Passenger-Connect-Password</em> HTTP header, like this:</p></d
|
|
3028
3350
|
<div class="listingblock">
|
3029
3351
|
<div class="content monospaced">
|
3030
3352
|
<pre>bash# curl -H "X-Passenger-Connect-Password: nFfVOX1F8LjZ90HJh28Sd_htJOsgRsNne2QXKf8NIXw" http://127.0.0.1:58122/</pre>
|
3031
|
-
</div
|
3353
|
+
</div>
|
3354
|
+
</div>
|
3032
3355
|
</div>
|
3033
3356
|
</div>
|
3034
3357
|
</div>
|
3035
3358
|
<div class="sect1">
|
3036
|
-
<h2 id="_tips">7. Tips</h2>
|
3359
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_tips" data-comment-topic="tips-n4c22d">7. Tips</h2>
|
3037
3360
|
<div class="sectionbody">
|
3038
3361
|
<div class="sect2">
|
3039
|
-
<h3 id="user_switching">7.1. User switching (security)</h3>
|
3362
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="user_switching" data-comment-topic="user-switching-security--zmsy9o">7.1. User switching (security)</h3>
|
3040
3363
|
<div class="paragraph"><p>There is a problem that plagues most PHP web hosts, namely the fact that all PHP
|
3041
3364
|
applications are run in the same user context as the web server. So for
|
3042
|
-
example, Joe
|
3365
|
+
example, Joe’s PHP application will be able to read Jane’s PHP application’s
|
3043
3366
|
passwords. This is obviously undesirable on many servers.</p></div>
|
3044
3367
|
<div class="paragraph"><p>Phusion Passenger solves this problem by implementing <em>user switching</em>. A Rails
|
3045
3368
|
application is started as the owner of the file <em>config/environment.rb</em>,
|
3046
3369
|
and a Rack application is started as the owner of the file <em>config.ru</em>.
|
3047
3370
|
So if <em>/home/webapps/foo/config/environment.rb</em> is owned by <em>joe</em>, then Phusion
|
3048
3371
|
Passenger will launch the corresponding Rails application as <em>joe</em> as well.</p></div>
|
3049
|
-
<div class="paragraph"><p>This behavior is the default, and you don
|
3372
|
+
<div class="paragraph"><p>This behavior is the default, and you don’t need to configure anything. But
|
3050
3373
|
there are things that you should keep in mind:</p></div>
|
3051
|
-
<div class="ulist"><ul>
|
3374
|
+
<div class="ulist"><ul>
|
3052
3375
|
<li>
|
3053
3376
|
<p>
|
3054
|
-
The owner of <em>environment.rb</em>/<em>config.ru</em> must have read access to the application
|
3055
|
-
root directory, and read/write access to the application
|
3377
|
+
The owner of <em>environment.rb</em>/<em>config.ru</em> must have read access to the application’s
|
3378
|
+
root directory, and read/write access to the application’s <em>logs</em> directory.
|
3056
3379
|
</p>
|
3057
3380
|
</li>
|
3058
3381
|
<li>
|
@@ -3076,17 +3399,17 @@ Under no circumstances will applications be run as <em>root</em>. If
|
|
3076
3399
|
option.</p></div>
|
3077
3400
|
</div>
|
3078
3401
|
<div class="sect2">
|
3079
|
-
<h3 id="reducing_memory_usage">7.2. Reducing memory consumption of Ruby on Rails applications by 33%</h3>
|
3402
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="reducing_memory_usage" data-comment-topic="reducing-memory-consumption-of-ruby-on-rails-applications-by-33--1o3z66q">7.2. Reducing memory consumption of Ruby on Rails applications by 33%</h3>
|
3080
3403
|
<div class="paragraph"><p>Is it possible to reduce memory consumption of your Rails applications by 33% on average,
|
3081
3404
|
by using <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>.
|
3082
3405
|
Please visit the website for details.</p></div>
|
3083
3406
|
<div class="paragraph"><p>Note that this feature does not apply to Rack applications.</p></div>
|
3084
3407
|
</div>
|
3085
3408
|
<div class="sect2">
|
3086
|
-
<h3 id="capistrano">7.3. Capistrano recipe</h3>
|
3409
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="capistrano" data-comment-topic="capistrano-recipe-pfn4qu">7.3. Capistrano recipe</h3>
|
3087
3410
|
<div class="paragraph"><p>Phusion Passenger can be combined with <a href="http://capify.org/">Capistrano</a>.
|
3088
3411
|
The following Capistrano recipe demonstrates Phusion Passenger support.
|
3089
|
-
It assumes that you
|
3412
|
+
It assumes that you’re using Git as version control system.</p></div>
|
3090
3413
|
<div class="listingblock">
|
3091
3414
|
<div class="content monospaced">
|
3092
3415
|
<pre>set :application, "myapp"
|
@@ -3114,13 +3437,14 @@ namespace :deploy do
|
|
3114
3437
|
run "touch #{current_release}/tmp/restart.txt"
|
3115
3438
|
end
|
3116
3439
|
end</pre>
|
3117
|
-
</div
|
3440
|
+
</div>
|
3441
|
+
</div>
|
3118
3442
|
</div>
|
3119
3443
|
<div class="sect2">
|
3120
|
-
<h3 id="bundler_support">7.4. Bundler support</h3>
|
3444
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="bundler_support" data-comment-topic="bundler-support-19v1h43">7.4. Bundler support</h3>
|
3121
3445
|
<div class="paragraph"><p>Phusion Passenger has automatic support for <a href="http://gembundler.com/git.html">Bundler</a>.
|
3122
3446
|
It works as follows:</p></div>
|
3123
|
-
<div class="ulist"><ul>
|
3447
|
+
<div class="ulist"><ul>
|
3124
3448
|
<li>
|
3125
3449
|
<p>
|
3126
3450
|
If you have a <em>.bundle/environment.rb</em> in your application root, then Phusion
|
@@ -3134,26 +3458,26 @@ Otherwise, if you have a <em>Gemfile</em>, then Phusion Passenger will automatic
|
|
3134
3458
|
</p>
|
3135
3459
|
</li>
|
3136
3460
|
</ul></div>
|
3137
|
-
<div class="paragraph"><p>It
|
3461
|
+
<div class="paragraph"><p>It’s possible that your application also calls <span class="monospaced">Bundler.setup</span> during loading, e.g. in
|
3138
3462
|
<em>config.ru</em> or in <em>config/boot.rb</em>. This is the case with Rails 3, and is also the case if you
|
3139
3463
|
modified your <em>config/boot.rb</em> according to the
|
3140
3464
|
<a href="http://gembundler.com/rails23.html">Bundler Rails 2.3 instructions</a>.
|
3141
3465
|
This leads to <span class="monospaced">Bundler.setup</span> being called twice, once before the application startup file
|
3142
|
-
is required and once during application startup. However this is harmless and doesn
|
3466
|
+
is required and once during application startup. However this is harmless and doesn’t
|
3143
3467
|
have any negative effects.</p></div>
|
3144
|
-
<div class="paragraph"><p>Phusion Passenger assumes that you
|
3468
|
+
<div class="paragraph"><p>Phusion Passenger assumes that you’re using Bundler >= 0.9.5. If you don’t want Phusion
|
3145
3469
|
Passenger to run its Bundler support code, e.g. because you need to use an older version
|
3146
3470
|
of Bundler with an incompatible API or because you use a system other than Bundler, then
|
3147
|
-
you can override Phusion Passenger
|
3471
|
+
you can override Phusion Passenger’s Bundler support code by creating a file
|
3148
3472
|
<em>config/setup_load_paths.rb</em>. If this file exists then it will be required before loading
|
3149
3473
|
the application startup file. In this file you can do whatever you need to setup Bundler
|
3150
3474
|
or a similar system.</p></div>
|
3151
3475
|
</div>
|
3152
3476
|
<div class="sect2">
|
3153
|
-
<h3 id="moving_phusion_passenger">7.5. Moving Phusion Passenger to a different directory</h3>
|
3477
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="moving_phusion_passenger" data-comment-topic="moving-phusion-passenger-to-a-different-directory-1hel5cp">7.5. Moving Phusion Passenger to a different directory</h3>
|
3154
3478
|
<div class="paragraph"><p>It is possible to relocate the Phusion Passenger files to a different directory. It
|
3155
3479
|
involves two steps:</p></div>
|
3156
|
-
<div class="olist arabic"><ol class="arabic">
|
3480
|
+
<div class="olist arabic"><ol class="arabic">
|
3157
3481
|
<li>
|
3158
3482
|
<p>
|
3159
3483
|
Moving the directory.
|
@@ -3161,13 +3485,13 @@ Moving the directory.
|
|
3161
3485
|
</li>
|
3162
3486
|
<li>
|
3163
3487
|
<p>
|
3164
|
-
Updating the
|
3488
|
+
Updating the “PassengerRoot” configuration option in Apache.
|
3165
3489
|
</p>
|
3166
3490
|
</li>
|
3167
3491
|
</ol></div>
|
3168
|
-
<div class="paragraph"><p>For example, if Phusion Passenger is located in <em>/opt/passenger/</em>, and you
|
3492
|
+
<div class="paragraph"><p>For example, if Phusion Passenger is located in <em>/opt/passenger/</em>, and you’d like to
|
3169
3493
|
move it to <em>/usr/local/passenger/</em>, then do this:</p></div>
|
3170
|
-
<div class="olist arabic"><ol class="arabic">
|
3494
|
+
<div class="olist arabic"><ol class="arabic">
|
3171
3495
|
<li>
|
3172
3496
|
<p>
|
3173
3497
|
Run the following command:
|
@@ -3175,7 +3499,8 @@ Run the following command:
|
|
3175
3499
|
<div class="listingblock">
|
3176
3500
|
<div class="content monospaced">
|
3177
3501
|
<pre>mv /opt/passenger /usr/local/passenger</pre>
|
3178
|
-
</div
|
3502
|
+
</div>
|
3503
|
+
</div>
|
3179
3504
|
</li>
|
3180
3505
|
<li>
|
3181
3506
|
<p>
|
@@ -3184,54 +3509,56 @@ Edit your Apache configuration file, and set:
|
|
3184
3509
|
<div class="listingblock">
|
3185
3510
|
<div class="content monospaced">
|
3186
3511
|
<pre>PassengerRoot /usr/local/passenger</pre>
|
3187
|
-
</div
|
3512
|
+
</div>
|
3513
|
+
</div>
|
3188
3514
|
</li>
|
3189
3515
|
</ol></div>
|
3190
3516
|
</div>
|
3191
3517
|
<div class="sect2">
|
3192
|
-
<h3 id="_installing_multiple_ruby_on_rails_versions">7.6. Installing multiple Ruby on Rails versions</h3>
|
3518
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_installing_multiple_ruby_on_rails_versions" data-comment-topic="installing-multiple-ruby-on-rails-versions-1bp1fff">7.6. Installing multiple Ruby on Rails versions</h3>
|
3193
3519
|
<div class="paragraph"><p>Each Ruby on Rails applications that are going to be deployed may require a
|
3194
3520
|
specific Ruby on Rails version. You can install a specific version with
|
3195
3521
|
this command:</p></div>
|
3196
3522
|
<div class="listingblock">
|
3197
3523
|
<div class="content monospaced">
|
3198
3524
|
<pre>gem install rails -v X.X.X</pre>
|
3199
|
-
</div
|
3525
|
+
</div>
|
3526
|
+
</div>
|
3200
3527
|
<div class="paragraph"><p>where <em>X.X.X</em> is the version number of Ruby on Rails.</p></div>
|
3201
3528
|
<div class="paragraph"><p>All of these versions will exist in parallel, and will not conflict with each
|
3202
3529
|
other. Phusion Passenger will automatically make use of the correct version.</p></div>
|
3203
3530
|
</div>
|
3204
3531
|
<div class="sect2">
|
3205
|
-
<h3 id="_making_the_application_restart_after_each_request">7.7. Making the application restart after each request</h3>
|
3532
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_making_the_application_restart_after_each_request" data-comment-topic="making-the-application-restart-after-each-request-vimy48">7.7. Making the application restart after each request</h3>
|
3206
3533
|
<div class="paragraph"><p>In some situations it might be desirable to restart the web application after
|
3207
|
-
each request, for example when developing a non-Rails application that doesn
|
3534
|
+
each request, for example when developing a non-Rails application that doesn’t
|
3208
3535
|
support code reloading, or when developing a web framework.</p></div>
|
3209
3536
|
<div class="paragraph"><p>To achieve this, simply create the file <em>tmp/always_restart.txt</em> in your
|
3210
|
-
application
|
3211
|
-
check for this file
|
3537
|
+
application’s root folder. Unlike <em>restart.txt</em>, Phusion Passenger does not
|
3538
|
+
check for this file’s timestamp: Phusion Passenger will always restart the
|
3212
3539
|
application, as long as <em>always_restart.txt</em> exists.</p></div>
|
3213
3540
|
<div class="admonitionblock">
|
3214
|
-
<table><tr>
|
3541
|
+
<table><tr>
|
3215
3542
|
<td class="icon">
|
3216
|
-
<img src="./images/icons/note.png" alt="Note">
|
3543
|
+
<img src="./images/icons/note.png" alt="Note">
|
3217
3544
|
</td>
|
3218
|
-
<td class="content">If you
|
3545
|
+
<td class="content">If you’re just developing a Rails application then you probably don’t need
|
3219
3546
|
this feature. If you set <em>RailsEnv development</em> in your Apache configuration,
|
3220
3547
|
then Rails will automatically reload your application code after each request.
|
3221
|
-
<em>always_restart.txt</em> is only useful if you
|
3222
|
-
or when you
|
3548
|
+
<em>always_restart.txt</em> is only useful if you’re working on Ruby on Rails itself,
|
3549
|
+
or when you’re not developing a Rails application and your web framework
|
3223
3550
|
does not support code reloading.</td>
|
3224
|
-
</tr></table>
|
3551
|
+
</tr></table>
|
3225
3552
|
</div>
|
3226
3553
|
</div>
|
3227
3554
|
<div class="sect2">
|
3228
|
-
<h3 id="sub_uri_deployment_uri_fix">7.8. How to fix broken images/CSS/JavaScript URIs in sub-URI deployments</h3>
|
3555
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="sub_uri_deployment_uri_fix" data-comment-topic="how-to-fix-broken-images-css-javascript-uris-in-sub-uri-deployments-11mzwt6">7.8. How to fix broken images/CSS/JavaScript URIs in sub-URI deployments</h3>
|
3229
3556
|
<div class="paragraph"><p>Some people experience broken images and other broken static assets when they
|
3230
3557
|
deploy their application to a sub-URI (i.e. <em>http://mysite.com/railsapp/</em>).
|
3231
3558
|
The reason for this usually is that you used a
|
3232
3559
|
static URI for your image in the views. This means your <em>img</em> source probably refers
|
3233
|
-
to something like <em>/images/foo.jpg</em>. The leading slash means that it
|
3234
|
-
you
|
3560
|
+
to something like <em>/images/foo.jpg</em>. The leading slash means that it’s an absolute URI:
|
3561
|
+
you’re telling the browser to always load <em>http://mysite.com/images/foo.jpg</em> no
|
3235
3562
|
matter what. The problem is that the image is actually at
|
3236
3563
|
<em>http://mysite.com/railsapp/images/foo.jpg</em>. There are two ways to fix this.</p></div>
|
3237
3564
|
<div class="paragraph"><p>The first way (not recommended) is to change your view templates to refer to
|
@@ -3239,23 +3566,24 @@ matter what. The problem is that the image is actually at
|
|
3239
3566
|
this does is making the path relative to the current URI. The problem is that if you
|
3240
3567
|
use restful URIs, then your images will probably break again when you add a level to
|
3241
3568
|
the URI.
|
3242
|
-
For example, when you
|
3243
|
-
<em>http://mysite.com/railsapp/images/foo.jpg</em>. But when you
|
3569
|
+
For example, when you’re at <em>http://mysite.com/railsapp</em> the browser will look for
|
3570
|
+
<em>http://mysite.com/railsapp/images/foo.jpg</em>. But when you’re at
|
3244
3571
|
<em>http://mysite.com/railsapp/controller</em>. the browser will look for
|
3245
3572
|
<em>http://mysite.com/railsapp/controller/images/foo.jpg</em>.
|
3246
|
-
So relative URIs usually don
|
3573
|
+
So relative URIs usually don’t work well with layout templates.</p></div>
|
3247
3574
|
<div class="paragraph"><p>The second and highly recommended way is to always use Rails helper methods to
|
3248
3575
|
output tags for static assets. These helper methods automatically take care
|
3249
|
-
of prepending the base URI that you
|
3576
|
+
of prepending the base URI that you’ve deployed the application to. For images
|
3250
3577
|
there is <span class="monospaced">image_tag</span>, for JavaScript there is <span class="monospaced">javascript_include_tag</span> and for
|
3251
3578
|
CSS there is <span class="monospaced">stylesheet_link_tag</span>. In the above example you would simply remove
|
3252
3579
|
the <em><img></em> HTML tag and replace it with inline Ruby like this:</p></div>
|
3253
3580
|
<div class="listingblock">
|
3254
3581
|
<div class="content monospaced">
|
3255
3582
|
<pre><%= image_tag("foo.jpg") %></pre>
|
3256
|
-
</div
|
3583
|
+
</div>
|
3584
|
+
</div>
|
3257
3585
|
<div class="paragraph"><p>This will generate the proper image tag to <span class="monospaced">$RAILS_ROOT/public/images/foo.jpg</span>
|
3258
|
-
so that your images will always work no matter what sub-URI you
|
3586
|
+
so that your images will always work no matter what sub-URI you’ve deployed to.</p></div>
|
3259
3587
|
<div class="paragraph"><p>These helper methods are more valuable than you may think. For example they also
|
3260
3588
|
append a timestamp to the URI to better facilitate HTTP caching. For more information,
|
3261
3589
|
please refer to
|
@@ -3264,13 +3592,13 @@ please refer to
|
|
3264
3592
|
</div>
|
3265
3593
|
</div>
|
3266
3594
|
<div class="sect1">
|
3267
|
-
<h2 id="_under_the_hood">8. Under the hood</h2>
|
3595
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_under_the_hood" data-comment-topic="under-the-hood-8uney">8. Under the hood</h2>
|
3268
3596
|
<div class="sectionbody">
|
3269
3597
|
<div class="paragraph"><p>Phusion Passenger hides a lot of complexity for the end user (i.e. the web server
|
3270
3598
|
system administrator), but sometimes it is desirable to know what is going on.
|
3271
3599
|
This section describes a few things that Phusion Passenger does under the hood.</p></div>
|
3272
3600
|
<div class="sect2">
|
3273
|
-
<h3 id="_page_caching_support">8.1. Page caching support</h3>
|
3601
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_page_caching_support" data-comment-topic="page-caching-support-nafhf6">8.1. Page caching support</h3>
|
3274
3602
|
<div class="paragraph"><p>For each HTTP request, Phusion Passenger will automatically look for a corresponding
|
3275
3603
|
page cache file, and serve that if it exists. It does this by appending ".html" to
|
3276
3604
|
the filename that the URI normally maps to, and checking whether that file exists.
|
@@ -3278,36 +3606,36 @@ This check occurs after checking whether the original mapped filename exists (as
|
|
3278
3606
|
of static asset serving). All this is done without the need for special mod_rewrite
|
3279
3607
|
rules.</p></div>
|
3280
3608
|
<div class="paragraph"><p>For example, suppose that the browser requests <em>/foo/bar</em>.</p></div>
|
3281
|
-
<div class="olist arabic"><ol class="arabic">
|
3609
|
+
<div class="olist arabic"><ol class="arabic">
|
3282
3610
|
<li>
|
3283
3611
|
<p>
|
3284
3612
|
Phusion Passenger will first check whether this URI maps to a static file, i.e.
|
3285
|
-
whether the file <em>foo/bar</em> exists in the web application
|
3613
|
+
whether the file <em>foo/bar</em> exists in the web application’s <em>public</em> directory.
|
3286
3614
|
If it does then Phusion Passenger will serve this file through Apache immediately.
|
3287
3615
|
</p>
|
3288
3616
|
</li>
|
3289
3617
|
<li>
|
3290
3618
|
<p>
|
3291
|
-
If that doesn
|
3619
|
+
If that doesn’t exist, then Phusion Passenger will check whether the file
|
3292
3620
|
<em>foo/bar.html</em> exists. If it does then Phusion Passenger will serve this file
|
3293
3621
|
through Apache immediately.
|
3294
3622
|
</p>
|
3295
3623
|
</li>
|
3296
3624
|
<li>
|
3297
3625
|
<p>
|
3298
|
-
If <em>foo/bar.html</em> doesn
|
3626
|
+
If <em>foo/bar.html</em> doesn’t exist either, then Phusion Passenger will forward the
|
3299
3627
|
request to the underlying web application.
|
3300
3628
|
</p>
|
3301
3629
|
</li>
|
3302
3630
|
</ol></div>
|
3303
|
-
<div class="paragraph"><p>Note that Phusion Passenger
|
3304
|
-
application uses a non-standard page cache directory, i.e. if it doesn
|
3305
|
-
the <em>public</em> directory. In that case you
|
3631
|
+
<div class="paragraph"><p>Note that Phusion Passenger’s page caching support doesn’t work if your web
|
3632
|
+
application uses a non-standard page cache directory, i.e. if it doesn’t cache to
|
3633
|
+
the <em>public</em> directory. In that case you’ll need to use mod_rewrite to serve such
|
3306
3634
|
page cache files.</p></div>
|
3307
3635
|
</div>
|
3308
3636
|
<div class="sect2">
|
3309
|
-
<h3 id="application_detection">8.2. How Phusion Passenger detects whether a virtual host is a web application</h3>
|
3310
|
-
<div class="paragraph"><p>After you
|
3637
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="application_detection" data-comment-topic="how-phusion-passenger-detects-whether-a-virtual-host-is-a-web-application-13qbmhn">8.2. How Phusion Passenger detects whether a virtual host is a web application</h3>
|
3638
|
+
<div class="paragraph"><p>After you’ve read the deployment instructions you might wonder how Phusion Passenger
|
3311
3639
|
knows that the server root points to a web application that Phusion Passenger is
|
3312
3640
|
able to serve, and how it knows what kind of web application it is (e.g. Rails or Rack).</p></div>
|
3313
3641
|
<div class="paragraph"><p>Phusion Passenger checks whether the virtual host is a Rails application by checking
|
@@ -3315,13 +3643,14 @@ whether the following file exists:</p></div>
|
|
3315
3643
|
<div class="listingblock">
|
3316
3644
|
<div class="content monospaced">
|
3317
3645
|
<pre>dirname(DocumentRoot) + "/config/environment.rb"</pre>
|
3318
|
-
</div
|
3319
|
-
|
3646
|
+
</div>
|
3647
|
+
</div>
|
3648
|
+
<div class="paragraph"><p>If you’re not a programmer and don’t understand the above pseudo-code snippet, it means
|
3320
3649
|
that Phusion Passenger will:</p></div>
|
3321
|
-
<div class="olist arabic"><ol class="arabic">
|
3650
|
+
<div class="olist arabic"><ol class="arabic">
|
3322
3651
|
<li>
|
3323
3652
|
<p>
|
3324
|
-
Extract the parent directory filename from the value of the
|
3653
|
+
Extract the parent directory filename from the value of the “root” directive.
|
3325
3654
|
</p>
|
3326
3655
|
</li>
|
3327
3656
|
<li>
|
@@ -3337,8 +3666,8 @@ whether the file <em>/webapps/foo/config/environment.rb</em> exists.</p></div>
|
|
3337
3666
|
So for example, suppose that your root points to <em>/home/www/example.com</em>, which in
|
3338
3667
|
turn is a symlink to <em>/webapps/example.com/public</em>. Phusion Passenger for Nginx will check for
|
3339
3668
|
<em>/home/www/config/environment.rb</em>, <strong>not</strong> <em>/webapps/example.com/config/environment.rb</em>.
|
3340
|
-
This file of course doesn
|
3341
|
-
itself for this virtual host, and you
|
3669
|
+
This file of course doesn’t exist, and as a result Phusion Passenger will not activate
|
3670
|
+
itself for this virtual host, and you’ll most likely see some output generated by the
|
3342
3671
|
Nginx default directory handler such as a Forbidden error message.</p></div>
|
3343
3672
|
<div class="paragraph"><p>Detection of Rack applications happens through the same mechanism, exception that
|
3344
3673
|
Phusion Passenger will look for <em>config.ru</em> instead of <em>config/environment.rb</em>.</p></div>
|
@@ -3346,31 +3675,29 @@ Phusion Passenger will look for <em>config.ru</em> instead of <em>config/environ
|
|
3346
3675
|
</div>
|
3347
3676
|
</div>
|
3348
3677
|
<div class="sect1">
|
3349
|
-
<h2 id="_appendix_a_about_this_document">9. Appendix A: About this document</h2>
|
3678
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_appendix_a_about_this_document" data-comment-topic="appendix-a-about-this-document-zfvixm">9. Appendix A: About this document</h2>
|
3350
3679
|
<div class="sectionbody">
|
3351
3680
|
<div class="paragraph"><p>The text of this document is licensed under the
|
3352
3681
|
<a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
|
3353
3682
|
Attribution-Share Alike 3.0 Unported License</a>.</p></div>
|
3354
3683
|
<div class="paragraph"><p><span class="image">
|
3355
3684
|
<a class="image" href="http://creativecommons.org/licenses/by-sa/3.0/">
|
3356
|
-
<img src="images/by_sa.png" alt="images/by_sa.png">
|
3357
|
-
</a>
|
3685
|
+
<img src="images/by_sa.png" alt="images/by_sa.png"></a>
|
3358
3686
|
</span></p></div>
|
3359
3687
|
<div class="paragraph"><p>Phusion Passenger is brought to you by <a href="http://www.phusion.nl/">Phusion</a>.</p></div>
|
3360
3688
|
<div class="paragraph"><p><span class="image">
|
3361
3689
|
<a class="image" href="http://www.phusion.nl/">
|
3362
|
-
<img src="images/phusion_banner.png" alt="images/phusion_banner.png">
|
3363
|
-
</a>
|
3690
|
+
<img src="images/phusion_banner.png" alt="images/phusion_banner.png"></a>
|
3364
3691
|
</span></p></div>
|
3365
3692
|
<div class="paragraph"><p>Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.</p></div>
|
3366
3693
|
</div>
|
3367
3694
|
</div>
|
3368
3695
|
<div class="sect1">
|
3369
|
-
<h2 id="_appendix_b_terminology">10. Appendix B: Terminology</h2>
|
3696
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="_appendix_b_terminology" data-comment-topic="appendix-b-terminology-wzv5ro">10. Appendix B: Terminology</h2>
|
3370
3697
|
<div class="sectionbody">
|
3371
3698
|
<div class="sect2">
|
3372
|
-
<h3 id="application_root">10.1. Application root</h3>
|
3373
|
-
<div class="paragraph"><p>The root directory of an application that
|
3699
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="application_root" data-comment-topic="application-root-1fd6bqv">10.1. Application root</h3>
|
3700
|
+
<div class="paragraph"><p>The root directory of an application that’s served by Phusion Passenger.</p></div>
|
3374
3701
|
<div class="paragraph"><p>In case of Ruby on Rails applications, this is the directory that contains
|
3375
3702
|
<em>Rakefile</em>, <em>app/</em>, <em>config/</em>, <em>public/</em>, etc. In other words, the directory
|
3376
3703
|
pointed to by <span class="monospaced">RAILS_ROOT</span>. For example, take the following directory structure:</p></div>
|
@@ -3397,7 +3724,8 @@ pointed to by <span class="monospaced">RAILS_ROOT</span>. For example, take the
|
|
3397
3724
|
| +- ...
|
3398
3725
|
|
|
3399
3726
|
+- ...</pre>
|
3400
|
-
</div
|
3727
|
+
</div>
|
3728
|
+
</div>
|
3401
3729
|
<div class="paragraph"><p>In case of Rack applications, this is the directory that contains <em>config.ru</em>.
|
3402
3730
|
For example, take the following directory structure:</p></div>
|
3403
3731
|
<div class="listingblock">
|
@@ -3411,7 +3739,8 @@ For example, take the following directory structure:</p></div>
|
|
3411
3739
|
+- config.ru
|
3412
3740
|
|
|
3413
3741
|
+- ...</pre>
|
3414
|
-
</div
|
3742
|
+
</div>
|
3743
|
+
</div>
|
3415
3744
|
<div class="paragraph"><p>In case of Python (WSGI) applications, this is the directory that contains
|
3416
3745
|
<em>passenger_wsgi.py</em>. For example, take the following directory structure:</p></div>
|
3417
3746
|
<div class="listingblock">
|
@@ -3425,31 +3754,32 @@ For example, take the following directory structure:</p></div>
|
|
3425
3754
|
+- passenger_wsgi.py
|
3426
3755
|
|
|
3427
3756
|
+- ...</pre>
|
3428
|
-
</div
|
3757
|
+
</div>
|
3758
|
+
</div>
|
3429
3759
|
</div>
|
3430
3760
|
</div>
|
3431
3761
|
</div>
|
3432
3762
|
<div class="sect1">
|
3433
|
-
<h2 id="spawning_methods_explained">11. Appendix C: Spawning methods explained</h2>
|
3763
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h2 id="spawning_methods_explained" data-comment-topic="appendix-c-spawning-methods-explained-tcp8e6">11. Appendix C: Spawning methods explained</h2>
|
3434
3764
|
<div class="sectionbody">
|
3435
3765
|
<div class="paragraph"><p>At its core, Phusion Passenger is an HTTP proxy and process manager. It spawns
|
3436
3766
|
Ruby on Rails/Rack/WSGI worker processes (which may also be referred to as
|
3437
3767
|
<em>backend processes</em>), and forwards incoming HTTP request to one of the worker
|
3438
3768
|
processes.</p></div>
|
3439
|
-
<div class="paragraph"><p>While this may sound simple, there
|
3440
|
-
Let
|
3441
|
-
assume that we
|
3769
|
+
<div class="paragraph"><p>While this may sound simple, there’s not just one way to spawn worker processes.
|
3770
|
+
Let’s go over the different spawning methods. For simplicity’s sake, let’s
|
3771
|
+
assume that we’re only talking about Ruby on Rails applications.</p></div>
|
3442
3772
|
<div class="sect2">
|
3443
|
-
<h3 id="_the_most_straightforward_and_traditional_way_conservative_spawning">11.1. The most straightforward and traditional way: conservative spawning</h3>
|
3773
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_the_most_straightforward_and_traditional_way_conservative_spawning" data-comment-topic="the-most-straightforward-and-traditional-way-conservative-spawning-civ29z">11.1. The most straightforward and traditional way: conservative spawning</h3>
|
3444
3774
|
<div class="paragraph"><p>Phusion Passenger could create a new Ruby process, which will then load the
|
3445
3775
|
Rails application along with the entire Rails framework. This process will then
|
3446
3776
|
enter an request handling main loop.</p></div>
|
3447
|
-
<div class="paragraph"><p>This is the most straightforward way to spawn worker processes. If you
|
3777
|
+
<div class="paragraph"><p>This is the most straightforward way to spawn worker processes. If you’re
|
3448
3778
|
familiar with the Mongrel application server, then this approach is exactly
|
3449
3779
|
what mongrel_cluster performs: it creates N worker processes, each which loads
|
3450
3780
|
a full copy of the Rails application and the Rails framework in memory. The Thin
|
3451
3781
|
application server employs pretty much the same approach.</p></div>
|
3452
|
-
<div class="paragraph"><p>Note that Phusion Passenger
|
3782
|
+
<div class="paragraph"><p>Note that Phusion Passenger’s version of conservative spawning differs slightly
|
3453
3783
|
from mongrel_cluster. Mongrel_cluster creates entirely new Ruby processes. In
|
3454
3784
|
programmers jargon, mongrel_cluster creates new Ruby processes by forking the
|
3455
3785
|
current process and exec()-ing a new Ruby interpreter. Phusion Passenger on the
|
@@ -3457,30 +3787,28 @@ other hand creates processes that reuse the already loaded Ruby interpreter. In
|
|
3457
3787
|
programmers jargon, Phusion Passenger calls fork(), but not exec().</p></div>
|
3458
3788
|
</div>
|
3459
3789
|
<div class="sect2">
|
3460
|
-
<h3 id="_the_smart_spawning_method">11.2. The smart spawning method</h3>
|
3790
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_the_smart_spawning_method" data-comment-topic="the-smart-spawning-method-7nhgtj">11.2. The smart spawning method</h3>
|
3461
3791
|
<div class="admonitionblock">
|
3462
|
-
<table><tr>
|
3792
|
+
<table><tr>
|
3463
3793
|
<td class="icon">
|
3464
|
-
<img src="./images/icons/note.png" alt="Note">
|
3794
|
+
<img src="./images/icons/note.png" alt="Note">
|
3465
3795
|
</td>
|
3466
3796
|
<td class="content">Smart spawning is supported for all Ruby applications but not for WSGI applications.</td>
|
3467
|
-
</tr></table>
|
3797
|
+
</tr></table>
|
3468
3798
|
</div>
|
3469
|
-
<div class="paragraph"><p>While conservative spawning works well, it
|
3799
|
+
<div class="paragraph"><p>While conservative spawning works well, it’s not as efficient as it could be
|
3470
3800
|
because each worker process has its own private copy of the Rails application
|
3471
3801
|
as well as the Rails framework. This wastes memory as well as startup time.</p></div>
|
3472
3802
|
<div class="paragraph"><p><span class="image">
|
3473
|
-
<img src="images/conservative_spawning.png" alt="Worker processes and conservative spawning">
|
3474
|
-
</span><br>
|
3475
|
-
<em>Figure: Worker processes and conservative spawning. Each worker process has its
|
3803
|
+
<img src="images/conservative_spawning.png" alt="Worker processes and conservative spawning"></span><br><em>Figure: Worker processes and conservative spawning. Each worker process has its
|
3476
3804
|
own private copy of the application code and Rails framework code.</em></p></div>
|
3477
3805
|
<div class="paragraph"><p>It is possible to make the different worker processes share the memory occupied
|
3478
3806
|
by application and Rails framework code, by utilizing so-called
|
3479
3807
|
copy-on-write semantics of the virtual memory system on modern operating
|
3480
3808
|
systems. As a side effect, the startup time is also reduced. This is technique
|
3481
|
-
is exploited by Phusion Passenger
|
3809
|
+
is exploited by Phusion Passenger’s <em>smart</em> and <em>smart-lv2</em> spawn methods.</p></div>
|
3482
3810
|
<div class="sect3">
|
3483
|
-
<h4 id="_how_it_works">11.2.1. How it works</h4>
|
3811
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_how_it_works" data-comment-topic="how-it-works-f9umga">11.2.1. How it works</h4>
|
3484
3812
|
<div class="paragraph"><p>When the <em>smart-lv2</em> spawn method is being used, Phusion Passenger will first
|
3485
3813
|
create a so-called <em>ApplicationSpawner server</em> process. This process loads the
|
3486
3814
|
entire Rails application along with the Rails framework, by loading
|
@@ -3490,15 +3818,13 @@ server will create a worker new process
|
|
3490
3818
|
that reuses the already loaded Rails application/framework. Creating a worker
|
3491
3819
|
process through an already running ApplicationSpawner server is very fast, about
|
3492
3820
|
10 times faster than loading the Rails application/framework from scratch. If
|
3493
|
-
the Ruby interpreter is copy-on-write friendly (that is, if you
|
3821
|
+
the Ruby interpreter is copy-on-write friendly (that is, if you’re running
|
3494
3822
|
<a href="#reducing_memory_usage">Ruby Enterprise Edition</a>) then all created worker
|
3495
3823
|
processes will share as much common
|
3496
3824
|
memory as possible. That is, they will all share the same application and Rails
|
3497
3825
|
framework code.</p></div>
|
3498
3826
|
<div class="paragraph"><p><span class="image">
|
3499
|
-
<img src="images/smart-lv2.png" alt="images/smart-lv2.png">
|
3500
|
-
</span><br>
|
3501
|
-
<em>Figure: Worker processes and the smart-lv2 spawn method. All worker processes,
|
3827
|
+
<img src="images/smart-lv2.png" alt="images/smart-lv2.png"></span><br><em>Figure: Worker processes and the smart-lv2 spawn method. All worker processes,
|
3502
3828
|
as well as the ApplicationSpawner, share the same application code and Rails
|
3503
3829
|
framework code.</em></p></div>
|
3504
3830
|
<div class="paragraph"><p>The <em>smart</em> spawn method goes even further, by caching the Rails framework in
|
@@ -3511,20 +3837,20 @@ ApplicationSpawner servers, will share the same Rails framework code.</p></div>
|
|
3511
3837
|
<div class="paragraph"><p>The <em>smart-lv2</em> method allows different worker processes that belong to the same
|
3512
3838
|
application to share memory. The <em>smart</em> method allows different worker
|
3513
3839
|
processes - that happen to use the same Rails version - to share memory, even if
|
3514
|
-
they don
|
3840
|
+
they don’t belong to the same application.</p></div>
|
3515
3841
|
<div class="paragraph"><p>Notes:</p></div>
|
3516
|
-
<div class="ulist"><ul>
|
3842
|
+
<div class="ulist"><ul>
|
3517
3843
|
<li>
|
3518
3844
|
<p>
|
3519
3845
|
Vendored Rails frameworks cannot be shared by different applications, even if
|
3520
3846
|
both vendored Rails frameworks are the same version. So for efficiency reasons
|
3521
|
-
we don
|
3847
|
+
we don’t recommend vendoring Rails.
|
3522
3848
|
</p>
|
3523
3849
|
</li>
|
3524
3850
|
<li>
|
3525
3851
|
<p>
|
3526
3852
|
ApplicationSpawner and FrameworkSpawner servers have an idle timeout just
|
3527
|
-
like worker processes. If an ApplicationSpawner/FrameworkSpawner server hasn
|
3853
|
+
like worker processes. If an ApplicationSpawner/FrameworkSpawner server hasn’t
|
3528
3854
|
been instructed to do anything for a while, it will be shutdown in order to
|
3529
3855
|
conserve memory. This idle timeout is configurable.
|
3530
3856
|
</p>
|
@@ -3532,10 +3858,10 @@ ApplicationSpawner and FrameworkSpawner servers have an idle timeout just
|
|
3532
3858
|
</ul></div>
|
3533
3859
|
</div>
|
3534
3860
|
<div class="sect3">
|
3535
|
-
<h4 id="_summary_of_benefits">11.2.2. Summary of benefits</h4>
|
3861
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_summary_of_benefits" data-comment-topic="summary-of-benefits-qovyvk">11.2.2. Summary of benefits</h4>
|
3536
3862
|
<div class="paragraph"><p>Suppose that Phusion Passenger needs a new worker process for an application
|
3537
3863
|
that uses Rails 2.2.1.</p></div>
|
3538
|
-
<div class="ulist"><ul>
|
3864
|
+
<div class="ulist"><ul>
|
3539
3865
|
<li>
|
3540
3866
|
<p>
|
3541
3867
|
If the <em>smart-lv2</em> spawning method is used, and an ApplicationSpawner server
|
@@ -3569,11 +3895,11 @@ gotchas you can easily reap the benefits of smart spawning.</p></div>
|
|
3569
3895
|
</div>
|
3570
3896
|
</div>
|
3571
3897
|
<div class="sect2">
|
3572
|
-
<h3 id="_smart_spawning_gotcha_1_unintentional_file_descriptor_sharing">11.3. Smart spawning gotcha #1: unintentional file descriptor sharing</h3>
|
3898
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_smart_spawning_gotcha_1_unintentional_file_descriptor_sharing" data-comment-topic="smart-spawning-gotcha-1-unintentional-file-descriptor-sharing-cebw6q">11.3. Smart spawning gotcha #1: unintentional file descriptor sharing</h3>
|
3573
3899
|
<div class="paragraph"><p>Because worker processes are created by forking from an ApplicationSpawner
|
3574
3900
|
server, it will share all file descriptors that are opened by the
|
3575
3901
|
ApplicationSpawner server. (This is part of the semantics of the Unix
|
3576
|
-
<em>fork()</em> system call. You might want to Google it if you
|
3902
|
+
<em>fork()</em> system call. You might want to Google it if you’re not familiar with
|
3577
3903
|
it.) A file descriptor is a handle which can be an opened file, an opened socket
|
3578
3904
|
connection, a pipe, etc. If different worker processes write to such a file
|
3579
3905
|
descriptor at the same time, then their write calls will be interleaved, which
|
@@ -3584,7 +3910,8 @@ Passenger is creating a new worker process. Phusion Passenger provides the API
|
|
3584
3910
|
call <span class="monospaced">PhusionPassenger.on_event(:starting_worker_process)</span> to do so. So you
|
3585
3911
|
could insert the following code in your <em>environment.rb</em>:</p></div>
|
3586
3912
|
<div class="listingblock">
|
3587
|
-
<div class="content"
|
3913
|
+
<div class="content">
|
3914
|
+
<!-- Generator: GNU source-highlight 2.11.1
|
3588
3915
|
by Lorenzo Bettini
|
3589
3916
|
http://www.lorenzobettini.it
|
3590
3917
|
http://www.gnu.org/software/src-highlite -->
|
@@ -3597,12 +3924,14 @@ http://www.gnu.org/software/src-highlite -->
|
|
3597
3924
|
<span style="font-style: italic"><span style="color: #9A1900"># We're in conservative spawning mode. We don't need to do anything.</span></span>
|
3598
3925
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3599
3926
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3600
|
-
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre
|
3927
|
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre>
|
3928
|
+
</div>
|
3929
|
+
</div>
|
3601
3930
|
<div class="paragraph"><p>Note that Phusion Passenger automatically reestablishes the connection to the
|
3602
3931
|
database upon creating a new worker process, which is why you normally do not
|
3603
3932
|
encounter any database issues when using smart spawning mode.</p></div>
|
3604
3933
|
<div class="sect3">
|
3605
|
-
<h4 id="_example_1_memcached_connection_sharing_harmful">11.3.1. Example 1: Memcached connection sharing (harmful)</h4>
|
3934
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_example_1_memcached_connection_sharing_harmful" data-comment-topic="example-1-memcached-connection-sharing-harmful--1wfs3ad">11.3.1. Example 1: Memcached connection sharing (harmful)</h4>
|
3606
3935
|
<div class="paragraph"><p>Suppose we have a Rails application that connects to a Memcached server in
|
3607
3936
|
<em>environment.rb</em>. This causes the ApplicationSpawner to have a socket connection
|
3608
3937
|
(file descriptor) to the Memcached server, as shown in the following figure:</p></div>
|
@@ -3611,7 +3940,8 @@ encounter any database issues when using smart spawning mode.</p></div>
|
|
3611
3940
|
<pre>+--------------------+
|
3612
3941
|
| ApplicationSpawner |-----------[Memcached server]
|
3613
3942
|
+--------------------+</pre>
|
3614
|
-
</div
|
3943
|
+
</div>
|
3944
|
+
</div>
|
3615
3945
|
<div class="paragraph"><p>Phusion Passenger then proceeds with creating a new Rails worker process, which
|
3616
3946
|
is to process incoming HTTP requests. The result will look like this:</p></div>
|
3617
3947
|
<div class="literalblock">
|
@@ -3623,7 +3953,8 @@ is to process incoming HTTP requests. The result will look like this:</p></div>
|
|
3623
3953
|
+--------------------+ |
|
3624
3954
|
| Worker process 1 |-----/
|
3625
3955
|
+--------------------+</pre>
|
3626
|
-
</div
|
3956
|
+
</div>
|
3957
|
+
</div>
|
3627
3958
|
<div class="paragraph"><p>Since a <em>fork()</em> makes a (virtual) complete copy of a process, all its file
|
3628
3959
|
descriptors will be copied as well. What we see here is that ApplicationSpawner
|
3629
3960
|
and Worker process 1 both share the same connection to Memcached.</p></div>
|
@@ -3643,11 +3974,12 @@ result is now as follows:</p></div>
|
|
3643
3974
|
+--------------------+ |
|
3644
3975
|
| Worker process 2 |-----/
|
3645
3976
|
+--------------------+</pre>
|
3646
|
-
</div
|
3977
|
+
</div>
|
3978
|
+
</div>
|
3647
3979
|
<div class="paragraph"><p>As you can see, Worker process 1 and Worker process 2 have the same Memcached
|
3648
3980
|
connection.</p></div>
|
3649
|
-
<div class="paragraph"><p>Suppose that users Joe and Jane visit your website at the same time. Joe
|
3650
|
-
request is handled by Worker process 1, and Jane
|
3981
|
+
<div class="paragraph"><p>Suppose that users Joe and Jane visit your website at the same time. Joe’s
|
3982
|
+
request is handled by Worker process 1, and Jane’s request is handled by Worker
|
3651
3983
|
process 2. Both worker processes want to fetch something from Memcached. Suppose
|
3652
3984
|
that in order to do that, both handlers need to send a "FETCH" command to Memcached.</p></div>
|
3653
3985
|
<div class="paragraph"><p>But suppose that, after worker process 1 having only sent "FE", a context switch
|
@@ -3674,11 +4006,13 @@ Memcached is forced to handle this as an error.</p></div>
|
|
3674
4006
|
+--------------------+ |
|
3675
4007
|
| |
|
3676
4008
|
+-------------------------------------+</pre>
|
3677
|
-
</div
|
4009
|
+
</div>
|
4010
|
+
</div>
|
3678
4011
|
<div class="paragraph"><p>Worker process 2 now has its own, separate communication channel with Memcached.
|
3679
4012
|
The code in <em>environment.rb</em> looks like this:</p></div>
|
3680
4013
|
<div class="listingblock">
|
3681
|
-
<div class="content"
|
4014
|
+
<div class="content">
|
4015
|
+
<!-- Generator: GNU source-highlight 2.11.1
|
3682
4016
|
by Lorenzo Bettini
|
3683
4017
|
http://www.lorenzobettini.it
|
3684
4018
|
http://www.gnu.org/software/src-highlite -->
|
@@ -3691,10 +4025,12 @@ http://www.gnu.org/software/src-highlite -->
|
|
3691
4025
|
<span style="font-style: italic"><span style="color: #9A1900"># We're in conservative spawning mode. We don't need to do anything.</span></span>
|
3692
4026
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3693
4027
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3694
|
-
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre
|
4028
|
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre>
|
4029
|
+
</div>
|
4030
|
+
</div>
|
3695
4031
|
</div>
|
3696
4032
|
<div class="sect3">
|
3697
|
-
<h4 id="_example_2_log_file_sharing_not_harmful">11.3.2. Example 2: Log file sharing (not harmful)</h4>
|
4033
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h4 id="_example_2_log_file_sharing_not_harmful" data-comment-topic="example-2-log-file-sharing-not-harmful--ox4yfy">11.3.2. Example 2: Log file sharing (not harmful)</h4>
|
3698
4034
|
<div class="paragraph"><p>There are also cases in which unintentional file descriptor sharing is not harmful.
|
3699
4035
|
One such case is log file file descriptor sharing. Even if two processes write
|
3700
4036
|
to the log file at the same time, the worst thing that can happen is that the
|
@@ -3702,18 +4038,19 @@ data in the log file is interleaved.</p></div>
|
|
3702
4038
|
<div class="paragraph"><p>To guarantee that the data written to the log file is never interleaved, you
|
3703
4039
|
must synchronize write access via an inter-process synchronization mechanism,
|
3704
4040
|
such as file locks. Reopening the log file, like you would have done in the
|
3705
|
-
Memcached example, doesn
|
4041
|
+
Memcached example, doesn’t help.</p></div>
|
3706
4042
|
</div>
|
3707
4043
|
</div>
|
3708
4044
|
<div class="sect2">
|
3709
|
-
<h3 id="_smart_spawning_gotcha_2_the_need_to_revive_threads">11.4. Smart spawning gotcha #2: the need to revive threads</h3>
|
3710
|
-
<div class="paragraph"><p>Another part of the <em>fork()</em> system call
|
3711
|
-
disappear after a fork call. So if you
|
4045
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_smart_spawning_gotcha_2_the_need_to_revive_threads" data-comment-topic="smart-spawning-gotcha-2-the-need-to-revive-threads-1ey176o">11.4. Smart spawning gotcha #2: the need to revive threads</h3>
|
4046
|
+
<div class="paragraph"><p>Another part of the <em>fork()</em> system call’s semantics is the fact that threads
|
4047
|
+
disappear after a fork call. So if you’ve created any threads in environment.rb,
|
3712
4048
|
then those threads will no longer be running in newly created worker process.
|
3713
4049
|
You need to revive them when a new worker process is created. Use the
|
3714
4050
|
<span class="monospaced">:starting_worker_process</span> event that Phusion Passenger provides, like this:</p></div>
|
3715
4051
|
<div class="listingblock">
|
3716
|
-
<div class="content"
|
4052
|
+
<div class="content">
|
4053
|
+
<!-- Generator: GNU source-highlight 2.11.1
|
3717
4054
|
by Lorenzo Bettini
|
3718
4055
|
http://www.lorenzobettini.it
|
3719
4056
|
http://www.gnu.org/software/src-highlite -->
|
@@ -3726,17 +4063,19 @@ http://www.gnu.org/software/src-highlite -->
|
|
3726
4063
|
<span style="font-style: italic"><span style="color: #9A1900"># We're in conservative spawning mode. We don't need to do anything.</span></span>
|
3727
4064
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3728
4065
|
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
|
3729
|
-
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre
|
4066
|
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre>
|
4067
|
+
</div>
|
4068
|
+
</div>
|
3730
4069
|
</div>
|
3731
4070
|
<div class="sect2">
|
3732
|
-
<h3 id="_smart_spawning_gotcha_3_code_load_order">11.5. Smart spawning gotcha #3: code load order</h3>
|
4071
|
+
<a href="javascript:void(0)" class="comments empty" title="Add a comment"><span class="count"></span></a><h3 id="_smart_spawning_gotcha_3_code_load_order" data-comment-topic="smart-spawning-gotcha-3-code-load-order-12ydsn8">11.5. Smart spawning gotcha #3: code load order</h3>
|
3733
4072
|
<div class="paragraph"><p>This gotcha is only applicable to the <em>smart</em> spawn method, not the <em>smart-lv2</em>
|
3734
4073
|
spawn method.</p></div>
|
3735
4074
|
<div class="paragraph"><p>If your application expects the Rails framework to be not loaded during the
|
3736
4075
|
beginning of <em>environment.rb</em>, then it can cause problems when an
|
3737
4076
|
ApplicationSpawner is created from a FrameworkSpawner, which already has the
|
3738
4077
|
Rails framework loaded. The most common case is when applications try to patch
|
3739
|
-
Rails by dropping a modified file that has the same name as Rails
|
4078
|
+
Rails by dropping a modified file that has the same name as Rails’s own file,
|
3740
4079
|
in a path that comes earlier in the Ruby search path.</p></div>
|
3741
4080
|
<div class="paragraph"><p>For example, suppose that we have an application which has a patched version
|
3742
4081
|
of <em>active_record/base.rb</em> located in <em>RAILS_ROOT/lib/patches</em>, and
|
@@ -3752,8 +4091,679 @@ has no effect.</p></div>
|
|
3752
4091
|
<div id="footnotes"><hr></div>
|
3753
4092
|
<div id="footer">
|
3754
4093
|
<div id="footer-text">
|
3755
|
-
Last updated 2012-
|
3756
|
-
</div>
|
3757
|
-
</div>
|
3758
|
-
|
3759
|
-
</html>
|
4094
|
+
Last updated 2012-06-14 09:44:53 CEST
|
4095
|
+
</div>
|
4096
|
+
</div>
|
4097
|
+
<script>/*! jQuery v1.7.1 jquery.com | jquery.org/license */
|
4098
|
+
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
|
4099
|
+
f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
|
4100
|
+
{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
|
4101
|
+
/**
|
4102
|
+
* jQuery hashchange 1.0.0
|
4103
|
+
*
|
4104
|
+
* (based on jquery.history)
|
4105
|
+
*
|
4106
|
+
* Copyright (c) 2008 Chris Leishman (chrisleishman.com)
|
4107
|
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
4108
|
+
* and GPL (GPL-LICENSE.txt) licenses.
|
4109
|
+
*/
|
4110
|
+
(function($) {
|
4111
|
+
|
4112
|
+
$.fn.extend({
|
4113
|
+
hashchange: function(callback) { this.bind('hashchange', callback) },
|
4114
|
+
openOnClick: function(href) {
|
4115
|
+
if (href === undefined || href.length == 0)
|
4116
|
+
href = '#';
|
4117
|
+
return this.click(function(ev) {
|
4118
|
+
if (href && href.charAt(0) == '#') {
|
4119
|
+
// execute load in separate call stack
|
4120
|
+
window.setTimeout(function() { $.locationHash(href) }, 0);
|
4121
|
+
} else {
|
4122
|
+
window.location(href);
|
4123
|
+
}
|
4124
|
+
ev.stopPropagation();
|
4125
|
+
return false;
|
4126
|
+
});
|
4127
|
+
}
|
4128
|
+
});
|
4129
|
+
|
4130
|
+
// IE 8 introduces the hashchange event natively - so nothing more to do
|
4131
|
+
if ($.browser.msie && document.documentMode && document.documentMode >= 8) {
|
4132
|
+
$.extend({
|
4133
|
+
locationHash: function(hash) {
|
4134
|
+
if (!hash) hash = '#';
|
4135
|
+
else if (hash.charAt(0) != '#') hash = '#' + hash;
|
4136
|
+
location.hash = hash;
|
4137
|
+
}
|
4138
|
+
});
|
4139
|
+
return;
|
4140
|
+
}
|
4141
|
+
|
4142
|
+
var curHash;
|
4143
|
+
// hidden iframe for IE (earlier than 8)
|
4144
|
+
var iframe;
|
4145
|
+
|
4146
|
+
$.extend({
|
4147
|
+
locationHash: function(hash) {
|
4148
|
+
if (curHash === undefined) return;
|
4149
|
+
|
4150
|
+
if (!hash) hash = '#';
|
4151
|
+
else if (hash.charAt(0) != '#') hash = '#' + hash;
|
4152
|
+
|
4153
|
+
location.hash = hash;
|
4154
|
+
|
4155
|
+
if (curHash == hash) return;
|
4156
|
+
curHash = hash;
|
4157
|
+
|
4158
|
+
if ($.browser.msie) updateIEFrame(hash);
|
4159
|
+
$.event.trigger('hashchange');
|
4160
|
+
}
|
4161
|
+
});
|
4162
|
+
|
4163
|
+
$(document).ready(function() {
|
4164
|
+
curHash = location.hash;
|
4165
|
+
if ($.browser.msie) {
|
4166
|
+
// stop the callback firing twice during init if no hash present
|
4167
|
+
if (curHash == '') curHash = '#';
|
4168
|
+
// add hidden iframe for IE
|
4169
|
+
iframe = $('<iframe />').hide().get(0);
|
4170
|
+
$('body').prepend(iframe);
|
4171
|
+
updateIEFrame(location.hash);
|
4172
|
+
setInterval(checkHashIE, 100);
|
4173
|
+
} else {
|
4174
|
+
setInterval(checkHash, 100);
|
4175
|
+
}
|
4176
|
+
});
|
4177
|
+
$(window).unload(function() { iframe = null });
|
4178
|
+
|
4179
|
+
function checkHash() {
|
4180
|
+
var hash = location.hash;
|
4181
|
+
if (hash != curHash) {
|
4182
|
+
curHash = hash;
|
4183
|
+
$.event.trigger('hashchange');
|
4184
|
+
}
|
4185
|
+
}
|
4186
|
+
|
4187
|
+
if ($.browser.msie) {
|
4188
|
+
// Attach a live handler for any anchor links
|
4189
|
+
$('a[href^=#]').live('click', function() {
|
4190
|
+
var hash = $(this).attr('href');
|
4191
|
+
// Don't intercept the click if there is an existing anchor on the page
|
4192
|
+
// that matches this hash
|
4193
|
+
if ($(hash).length == 0 && $('a[name='+hash.slice(1)+']').length == 0) {
|
4194
|
+
$.locationHash(hash);
|
4195
|
+
return false;
|
4196
|
+
}
|
4197
|
+
});
|
4198
|
+
}
|
4199
|
+
|
4200
|
+
function checkHashIE() {
|
4201
|
+
// On IE, check for location.hash of iframe
|
4202
|
+
var idoc = iframe.contentDocument || iframe.contentWindow.document;
|
4203
|
+
var hash = idoc.location.hash;
|
4204
|
+
if (hash == '') hash = '#';
|
4205
|
+
|
4206
|
+
if (hash != curHash) {
|
4207
|
+
if (location.hash != hash) location.hash = hash;
|
4208
|
+
curHash = hash;
|
4209
|
+
$.event.trigger('hashchange');
|
4210
|
+
}
|
4211
|
+
}
|
4212
|
+
|
4213
|
+
function updateIEFrame(hash) {
|
4214
|
+
if (hash == '#') hash = '';
|
4215
|
+
var idoc = iframe.contentWindow.document;
|
4216
|
+
idoc.open();
|
4217
|
+
idoc.close();
|
4218
|
+
if (idoc.location.hash != hash) idoc.location.hash = hash;
|
4219
|
+
}
|
4220
|
+
|
4221
|
+
})(jQuery);
|
4222
|
+
// IE...
|
4223
|
+
if (!Date.now) {
|
4224
|
+
Date.now = function() {
|
4225
|
+
return new Date().getTime();
|
4226
|
+
}
|
4227
|
+
}
|
4228
|
+
|
4229
|
+
var Mizuho = {
|
4230
|
+
/** Cached DOM elements so that we don't have to re-find them over and over. */
|
4231
|
+
$document: undefined,
|
4232
|
+
$window: undefined,
|
4233
|
+
$mainSections: undefined,
|
4234
|
+
$sectionHeaders: undefined,
|
4235
|
+
|
4236
|
+
/** Constants */
|
4237
|
+
MAX_TOC_LEVEL: 3,
|
4238
|
+
|
4239
|
+
sectionHeadersSelector: undefined,
|
4240
|
+
scrollMemory: {},
|
4241
|
+
changingHash: false,
|
4242
|
+
activeHash: undefined,
|
4243
|
+
/** Whether in single-page or multi-page mode. Either 'single' or 'multi'. */
|
4244
|
+
mode: 'single',
|
4245
|
+
/** Whether smooth scrolling is enabled. It is always enabled except right
|
4246
|
+
* after page load: when the page is scrolled to the section as pointed to
|
4247
|
+
* by location.hash.
|
4248
|
+
*/
|
4249
|
+
smoothScrolling: true,
|
4250
|
+
|
4251
|
+
initialize: function() {
|
4252
|
+
this.sectionHeadersSelector = '';
|
4253
|
+
for (var i = 0; i < this.MAX_TOC_LEVEL; i++) {
|
4254
|
+
if (i != 0) {
|
4255
|
+
this.sectionHeadersSelector += ', ';
|
4256
|
+
}
|
4257
|
+
this.sectionHeadersSelector += 'h' + (i + 2);
|
4258
|
+
}
|
4259
|
+
|
4260
|
+
this.$document = $(document);
|
4261
|
+
this.$window = $(window);
|
4262
|
+
this.$mainSections = $('.sect1');
|
4263
|
+
this.$sectionHeaders = $(this.sectionHeadersSelector, '#content');
|
4264
|
+
this.$sectionHeaders.sort(function(a, b) {
|
4265
|
+
var off_a = $(a).offset();
|
4266
|
+
var off_b = $(b).offset();
|
4267
|
+
return off_a.top - off_b.top;
|
4268
|
+
});
|
4269
|
+
|
4270
|
+
if (this.isMobileDevice()) {
|
4271
|
+
$(document.body).addClass('mobile');
|
4272
|
+
}
|
4273
|
+
},
|
4274
|
+
|
4275
|
+
|
4276
|
+
/********* Generic utility functions *********/
|
4277
|
+
|
4278
|
+
isMobileDevice: function() {
|
4279
|
+
return navigator.userAgent.match(
|
4280
|
+
/(IEMobile|Windows CE|NetFront|PlayStation|PLAYSTATION|like Mac OS X|MIDP|UP\.Browser|Symbian|Nintendo|Android)/
|
4281
|
+
);
|
4282
|
+
},
|
4283
|
+
|
4284
|
+
virtualAnimate: function(options) {
|
4285
|
+
var options = $.extend({
|
4286
|
+
duration: 1000
|
4287
|
+
}, options || {});
|
4288
|
+
var animation_start = Date.now();
|
4289
|
+
var animation_end = Date.now() + options.duration;
|
4290
|
+
var interval = animation_end - animation_start;
|
4291
|
+
this._virtualAnimate_step(animation_start, animation_end, interval, options);
|
4292
|
+
},
|
4293
|
+
|
4294
|
+
_virtualAnimate_step: function(animation_start, animation_end, interval, options) {
|
4295
|
+
var self = this;
|
4296
|
+
var now = new Date();
|
4297
|
+
var progress = (now - animation_start) / interval;
|
4298
|
+
if (progress > 1) {
|
4299
|
+
progress = 1;
|
4300
|
+
}
|
4301
|
+
progress = (1 + Math.sin(-Math.PI / 2 + progress * Math.PI)) / 2;
|
4302
|
+
options.step(progress);
|
4303
|
+
if (now < animation_end) {
|
4304
|
+
setTimeout(function() {
|
4305
|
+
self._virtualAnimate_step(animation_start,
|
4306
|
+
animation_end, interval, options);
|
4307
|
+
}, 15);
|
4308
|
+
} else {
|
4309
|
+
options.step(1);
|
4310
|
+
if (options.finish) {
|
4311
|
+
options.finish();
|
4312
|
+
}
|
4313
|
+
}
|
4314
|
+
},
|
4315
|
+
|
4316
|
+
smoothlyScrollTo: function(top) {
|
4317
|
+
if (!this.smoothScrolling) {
|
4318
|
+
return this.setScrollTop(top);
|
4319
|
+
}
|
4320
|
+
|
4321
|
+
var self = this;
|
4322
|
+
var $document = this.$document;
|
4323
|
+
var current = $document.scrollTop();
|
4324
|
+
this.virtualAnimate({
|
4325
|
+
duration: 300,
|
4326
|
+
step: function(x) {
|
4327
|
+
$document.scrollTop(Math.floor(
|
4328
|
+
top + (1 - x) * (current - top)
|
4329
|
+
));
|
4330
|
+
},
|
4331
|
+
finish: function() {
|
4332
|
+
self.setScrollTop(top);
|
4333
|
+
}
|
4334
|
+
});
|
4335
|
+
},
|
4336
|
+
|
4337
|
+
smoothlyScrollToToc: function() {
|
4338
|
+
this.smoothlyScrollTo($('#toc').position().top);
|
4339
|
+
},
|
4340
|
+
|
4341
|
+
scrollToHeader: function(header) {
|
4342
|
+
this.smoothlyScrollTo($(header).offset().top - 50);
|
4343
|
+
},
|
4344
|
+
|
4345
|
+
setScrollTop: function(top, element) {
|
4346
|
+
// Browsers don't always scroll properly so work around
|
4347
|
+
// this with a few timers.
|
4348
|
+
var self = this;
|
4349
|
+
element = element || this.$document;
|
4350
|
+
element = $(element);
|
4351
|
+
element.scrollTop(top);
|
4352
|
+
setTimeout(function() {
|
4353
|
+
element.scrollTop(top);
|
4354
|
+
}, 1);
|
4355
|
+
setTimeout(function() {
|
4356
|
+
element.scrollTop(top);
|
4357
|
+
self.$document.trigger('mizuho:updateTopBar');
|
4358
|
+
}, 20);
|
4359
|
+
},
|
4360
|
+
|
4361
|
+
|
4362
|
+
/********* Mizuho-specific functions *********/
|
4363
|
+
|
4364
|
+
/** Returns the currently displayed section's header DOM element. */
|
4365
|
+
currentSubsection: function() {
|
4366
|
+
var $sectionHeaders = this.$sectionHeaders;
|
4367
|
+
var scrollTop = this.$document.scrollTop();
|
4368
|
+
var windowHeight = this.$window.height();
|
4369
|
+
var offset;
|
4370
|
+
|
4371
|
+
var low = 0;
|
4372
|
+
var high = this.$sectionHeaders.length - 1;
|
4373
|
+
var mid = 0;
|
4374
|
+
|
4375
|
+
while (low <= high) {
|
4376
|
+
mid = Math.floor((low + high) / 2);
|
4377
|
+
offset = $($sectionHeaders[mid]).offset();
|
4378
|
+
|
4379
|
+
if (offset.top >= scrollTop) {
|
4380
|
+
high = mid - 1;
|
4381
|
+
} else {
|
4382
|
+
low = mid + 1;
|
4383
|
+
}
|
4384
|
+
}
|
4385
|
+
|
4386
|
+
var $found = $($sectionHeaders[low]);
|
4387
|
+
if ($found.offset().top > scrollTop + windowHeight) {
|
4388
|
+
if (low > 0) {
|
4389
|
+
return $sectionHeaders[low - 1];
|
4390
|
+
} else {
|
4391
|
+
return undefined;
|
4392
|
+
}
|
4393
|
+
} else {
|
4394
|
+
return $sectionHeaders[low];
|
4395
|
+
}
|
4396
|
+
},
|
4397
|
+
|
4398
|
+
/** Looks up a section's header DOM element corresponding to a hash name. */
|
4399
|
+
lookupHeader: function(hash) {
|
4400
|
+
var id = hash.replace(/^#!\//, '#');
|
4401
|
+
if (id == '') {
|
4402
|
+
return undefined;
|
4403
|
+
} else {
|
4404
|
+
var header = $(id);
|
4405
|
+
if (header.length == 0) {
|
4406
|
+
return undefined;
|
4407
|
+
} else {
|
4408
|
+
return header;
|
4409
|
+
}
|
4410
|
+
}
|
4411
|
+
}
|
4412
|
+
};
|
4413
|
+
|
4414
|
+
for (var key in Mizuho) {
|
4415
|
+
if (typeof(Mizuho[key]) == 'function') {
|
4416
|
+
Mizuho[key] = $.proxy(Mizuho[key], Mizuho);
|
4417
|
+
}
|
4418
|
+
}
|
4419
|
+
$(document).ready(Mizuho.initialize);
|
4420
|
+
//$(document).ready(Mizuho.installHashbangLinks);
|
4421
|
+
|
4422
|
+
Mizuho.initializeTopBar = $.proxy(function() {
|
4423
|
+
var $window = this.$window;
|
4424
|
+
var $document = this.$document;
|
4425
|
+
var self = this;
|
4426
|
+
var $topbar = $('#topbar');
|
4427
|
+
var $title = $('#header h1');
|
4428
|
+
var $currentSection = $('#current_section');
|
4429
|
+
var isMobileDevice = this.isMobileDevice();
|
4430
|
+
var timerId;
|
4431
|
+
|
4432
|
+
var $floattoc = $('<div id="floattoc"></div>').html($('#toc').html());
|
4433
|
+
$floattoc.find('#toctitle').remove();
|
4434
|
+
$floattoc.find('.comments').remove();
|
4435
|
+
$floattoc.css('visibility', 'hidden');
|
4436
|
+
$floattoc.insertAfter($topbar);
|
4437
|
+
var $floattoclinks = $floattoc.find('a');
|
4438
|
+
$floattoclinks.each(function() {
|
4439
|
+
// Firefox changes '#!' to '#%21' so change that back.
|
4440
|
+
var $this = $(this);
|
4441
|
+
var href = $this.attr('href');
|
4442
|
+
if (href.match(/^#%21/)) {
|
4443
|
+
$this.attr('href', href.replace(/^#%21/, '#!'));
|
4444
|
+
}
|
4445
|
+
});
|
4446
|
+
$floattoclinks.click(function(event) {
|
4447
|
+
self.internalLinkClicked(this, event);
|
4448
|
+
});
|
4449
|
+
|
4450
|
+
function showFloatingToc() {
|
4451
|
+
var scrollUpdateTimerId;
|
4452
|
+
|
4453
|
+
function reposition() {
|
4454
|
+
if (isMobileDevice) {
|
4455
|
+
$floattoc.css({
|
4456
|
+
top: $currentSection.offset().top +
|
4457
|
+
$currentSection.innerHeight() +
|
4458
|
+
'px',
|
4459
|
+
height: $window.height() * 0.7 + 'px'
|
4460
|
+
});
|
4461
|
+
}
|
4462
|
+
}
|
4463
|
+
|
4464
|
+
function highlightCurrentTocEntry() {
|
4465
|
+
var currentSubsection = self.currentSubsection();
|
4466
|
+
$floattoclinks.removeClass('current');
|
4467
|
+
if (currentSubsection) {
|
4468
|
+
var currentSubsectionTitle = $(currentSubsection).text();
|
4469
|
+
var $link;
|
4470
|
+
|
4471
|
+
$floattoclinks.each(function() {
|
4472
|
+
if ($(this).text() == currentSubsectionTitle) {
|
4473
|
+
$link = $(this);
|
4474
|
+
return false;
|
4475
|
+
}
|
4476
|
+
});
|
4477
|
+
if ($link) {
|
4478
|
+
$link.addClass('current');
|
4479
|
+
self.setScrollTop(
|
4480
|
+
$floattoc.scrollTop() +
|
4481
|
+
$link.position().top -
|
4482
|
+
$floattoc.height() * 0.45,
|
4483
|
+
$floattoc);
|
4484
|
+
return false;
|
4485
|
+
}
|
4486
|
+
}
|
4487
|
+
}
|
4488
|
+
|
4489
|
+
function hideFloatingToc() {
|
4490
|
+
$currentSection.removeClass('pressed');
|
4491
|
+
$floattoc.css('visibility', 'hidden');
|
4492
|
+
$floattoclinks.unbind('click', hideFloatingToc);
|
4493
|
+
$document.unbind('mousedown', onMouseDown);
|
4494
|
+
$document.unbind('touchdown', onMouseDown);
|
4495
|
+
$document.unbind('mizuho:hideTopBar', hideFloatingToc);
|
4496
|
+
$window.unbind('scroll', onScroll);
|
4497
|
+
if (scrollUpdateTimerId !== undefined) {
|
4498
|
+
clearTimeout(scrollUpdateTimerId);
|
4499
|
+
scrollUpdateTimerId = undefined;
|
4500
|
+
}
|
4501
|
+
}
|
4502
|
+
|
4503
|
+
function onMouseDown(event) {
|
4504
|
+
if (event.target != $floattoc[0]
|
4505
|
+
&& $(event.target).closest('#floattoc').length == 0) {
|
4506
|
+
hideFloatingToc();
|
4507
|
+
}
|
4508
|
+
}
|
4509
|
+
|
4510
|
+
function onScroll(event) {
|
4511
|
+
if (scrollUpdateTimerId === undefined) {
|
4512
|
+
scrollUpdateTimerId = setTimeout(function() {
|
4513
|
+
scrollUpdateTimerId = undefined;
|
4514
|
+
reposition();
|
4515
|
+
highlightCurrentTocEntry();
|
4516
|
+
}, 100);
|
4517
|
+
}
|
4518
|
+
}
|
4519
|
+
|
4520
|
+
// Layout and display floating TOC.
|
4521
|
+
highlightCurrentTocEntry();
|
4522
|
+
var origScrollTop = $document.scrollTop();
|
4523
|
+
var windowWidth = $window.width();
|
4524
|
+
var maxRight = windowWidth - Math.floor(windowWidth * 0.1);
|
4525
|
+
|
4526
|
+
if ($currentSection.offset().left + $floattoc.outerWidth() > maxRight) {
|
4527
|
+
$floattoc.css('left', maxRight - $floattoc.outerWidth());
|
4528
|
+
} else {
|
4529
|
+
$floattoc.css('left', $currentSection.offset().left + 'px');
|
4530
|
+
}
|
4531
|
+
reposition();
|
4532
|
+
$floattoc.css('visibility', 'visible');
|
4533
|
+
$currentSection.addClass('pressed');
|
4534
|
+
|
4535
|
+
$floattoclinks.bind('click', hideFloatingToc);
|
4536
|
+
$document.bind('mousedown', onMouseDown)
|
4537
|
+
$document.bind('touchdown', onMouseDown);
|
4538
|
+
$document.bind('mizuho:hideTopBar', hideFloatingToc);
|
4539
|
+
$window.bind('scroll', onScroll);
|
4540
|
+
}
|
4541
|
+
|
4542
|
+
function update() {
|
4543
|
+
if ($title.offset().top + $title.height() < $document.scrollTop()) {
|
4544
|
+
if (!$topbar.is(':visible')) {
|
4545
|
+
$topbar.slideDown(250);
|
4546
|
+
$document.trigger('mizuho:showTopBar');
|
4547
|
+
}
|
4548
|
+
} else {
|
4549
|
+
if ($topbar.is(':visible')) {
|
4550
|
+
$topbar.slideUp();
|
4551
|
+
$document.trigger('mizuho:hideTopBar');
|
4552
|
+
}
|
4553
|
+
}
|
4554
|
+
|
4555
|
+
if (isMobileDevice) {
|
4556
|
+
$topbar.css({
|
4557
|
+
top: $document.scrollTop() + 'px',
|
4558
|
+
width: $window.width() -
|
4559
|
+
parseInt($topbar.css('padding-left')) -
|
4560
|
+
parseInt($topbar.css('padding-right')) +
|
4561
|
+
'px'
|
4562
|
+
});
|
4563
|
+
}
|
4564
|
+
|
4565
|
+
var header = self.currentSubsection();
|
4566
|
+
var name;
|
4567
|
+
if (header) {
|
4568
|
+
name = $(header).text();
|
4569
|
+
} else {
|
4570
|
+
name = 'Preamble';
|
4571
|
+
}
|
4572
|
+
$currentSection.text(name);
|
4573
|
+
}
|
4574
|
+
|
4575
|
+
function scheduleUpdate() {
|
4576
|
+
if (timerId !== undefined) {
|
4577
|
+
return;
|
4578
|
+
}
|
4579
|
+
timerId = setTimeout(function() {
|
4580
|
+
timerId = undefined;
|
4581
|
+
update();
|
4582
|
+
}, 100);
|
4583
|
+
}
|
4584
|
+
|
4585
|
+
if (isMobileDevice) {
|
4586
|
+
// Mobile devices don't support position fixed.
|
4587
|
+
$topbar.css('position', 'absolute');
|
4588
|
+
$floattoc.css('position', 'absolute');
|
4589
|
+
}
|
4590
|
+
|
4591
|
+
$currentSection.click(showFloatingToc);
|
4592
|
+
$window.scroll(scheduleUpdate);
|
4593
|
+
$document.bind('mizuho:updateTopBar', update);
|
4594
|
+
}, Mizuho);
|
4595
|
+
|
4596
|
+
$(document).ready(Mizuho.initializeTopBar);
|
4597
|
+
|
4598
|
+
|
4599
|
+
var JUVIA_URL = 'http://juvia.phusion.nl';
|
4600
|
+
var JUVIA_SITE_KEY = 'q0ptarhn8o9xanwomq8zkgewbtwffyz';
|
4601
|
+
var disqus_identifier;
|
4602
|
+
var disqus_title;
|
4603
|
+
var disqus_url;
|
4604
|
+
var disqus_developer = 1;
|
4605
|
+
|
4606
|
+
Mizuho.initializeCommenting = $.proxy(function() {
|
4607
|
+
var self = this;
|
4608
|
+
this.commentBalloons = $('.comments');
|
4609
|
+
this.commentBalloons.click(function() {
|
4610
|
+
self.showCommentsPopup(this);
|
4611
|
+
});
|
4612
|
+
this.reloadCommentCount();
|
4613
|
+
}, Mizuho);
|
4614
|
+
|
4615
|
+
Mizuho.showLightbox = $.proxy(function(creationCallback, closeCallback) {
|
4616
|
+
var lightbox = $(
|
4617
|
+
'<div id="comments_lightbox">' +
|
4618
|
+
' <div id="comments_lightbox_shadow"></div>' +
|
4619
|
+
' <div id="comments_lightbox_contents"><div class="shell"></div></div>' +
|
4620
|
+
'</div>');
|
4621
|
+
var shadow = $('#comments_lightbox_shadow', lightbox);
|
4622
|
+
var contents = $('#comments_lightbox_contents > .shell', lightbox);
|
4623
|
+
|
4624
|
+
function close() {
|
4625
|
+
if (lightbox) {
|
4626
|
+
lightbox.remove();
|
4627
|
+
lightbox = undefined;
|
4628
|
+
if (closeCallback) {
|
4629
|
+
closeCallback();
|
4630
|
+
}
|
4631
|
+
}
|
4632
|
+
}
|
4633
|
+
|
4634
|
+
shadow.click(close);
|
4635
|
+
lightbox.bind('lightbox:close', close);
|
4636
|
+
lightbox.appendTo(document.body);
|
4637
|
+
creationCallback(contents);
|
4638
|
+
}, Mizuho);
|
4639
|
+
|
4640
|
+
Mizuho.getCommentThreadInfo = $.proxy(function(balloon) {
|
4641
|
+
var info = {};
|
4642
|
+
if ($(balloon).closest('#toc').length > 0) {
|
4643
|
+
info.id = 'toctitle';
|
4644
|
+
info.topic = 'toctitle';
|
4645
|
+
info.title = $('#header h1').text() + " - " + $('#toctitle').text();
|
4646
|
+
} else {
|
4647
|
+
var header = $(balloon).next('h2, h3, h4');
|
4648
|
+
if (header.length > 0) {
|
4649
|
+
info.id = header.attr('id');
|
4650
|
+
info.topic = header.data('comment-topic');
|
4651
|
+
info.title = $('#header h1').text() + " - " + header.text();
|
4652
|
+
} else {
|
4653
|
+
info = undefined;
|
4654
|
+
}
|
4655
|
+
}
|
4656
|
+
return info;
|
4657
|
+
}, Mizuho);
|
4658
|
+
|
4659
|
+
Mizuho.callJuviaApi = function(action, options) {
|
4660
|
+
function makeQueryString(options) {
|
4661
|
+
var key, params = [];
|
4662
|
+
for (key in options) {
|
4663
|
+
params.push(
|
4664
|
+
encodeURIComponent(key) +
|
4665
|
+
'=' +
|
4666
|
+
encodeURIComponent(options[key]));
|
4667
|
+
}
|
4668
|
+
return params.join('&');
|
4669
|
+
}
|
4670
|
+
|
4671
|
+
// Makes sure that each call generates a unique URL, otherwise
|
4672
|
+
// the browser may not actually perform the request.
|
4673
|
+
if (!('_juviaRequestCounter' in window)) {
|
4674
|
+
window._juviaRequestCounter = 0;
|
4675
|
+
}
|
4676
|
+
|
4677
|
+
var url =
|
4678
|
+
JUVIA_URL + '/api/' + action +
|
4679
|
+
'?_c=' + window._juviaRequestCounter +
|
4680
|
+
'&' + makeQueryString(options);
|
4681
|
+
window._juviaRequestCounter++;
|
4682
|
+
|
4683
|
+
var s = document.createElement('script');
|
4684
|
+
s.async = true;
|
4685
|
+
s.type = 'text/javascript';
|
4686
|
+
s.className = 'juvia';
|
4687
|
+
s.src = url;
|
4688
|
+
(document.getElementsByTagName('head')[0] ||
|
4689
|
+
document.getElementsByTagName('body')[0]).appendChild(s);
|
4690
|
+
}
|
4691
|
+
|
4692
|
+
Mizuho.showCommentsPopup = $.proxy(function(balloon) {
|
4693
|
+
var info = this.getCommentThreadInfo(balloon);
|
4694
|
+
if (!info) {
|
4695
|
+
return;
|
4696
|
+
}
|
4697
|
+
|
4698
|
+
var self = this;
|
4699
|
+
this.showLightbox(function(element) {
|
4700
|
+
// We install a 'Close' button in the Juvia comment form after it has loaded.
|
4701
|
+
function installCloseButton() {
|
4702
|
+
if ($('#comments .juvia-form-actions').size() > 0) {
|
4703
|
+
// The Juvia form is now loaded. Install the button.
|
4704
|
+
var div = $('<div class="juvia-action" style="margin-left: 0.5em"></div>');
|
4705
|
+
var button = $('<input type="button" value="Cancel"></div>').appendTo(div);
|
4706
|
+
div.insertBefore('#comments .juvia-form-actions .juvia-error');
|
4707
|
+
button.click(function() {
|
4708
|
+
$(element).trigger('lightbox:close');
|
4709
|
+
});
|
4710
|
+
} else {
|
4711
|
+
// Continue polling.
|
4712
|
+
setTimeout(installCloseButton, 50);
|
4713
|
+
}
|
4714
|
+
}
|
4715
|
+
setTimeout(installCloseButton, 50);
|
4716
|
+
|
4717
|
+
// Now load the Juvia comments form.
|
4718
|
+
element.html('<div id="comments">Loading comments...</div>');
|
4719
|
+
self.changingHash = true;
|
4720
|
+
location.hash = '#!/' + info.id;
|
4721
|
+
self.callJuviaApi('show_topic.js', {
|
4722
|
+
container : '#comments',
|
4723
|
+
site_key : JUVIA_SITE_KEY,
|
4724
|
+
topic_key : info.topic,
|
4725
|
+
topic_url : location.href,
|
4726
|
+
topic_title : info.topic,
|
4727
|
+
include_base: !window.Juvia,
|
4728
|
+
include_css : !window.Juvia
|
4729
|
+
});
|
4730
|
+
}, function() {
|
4731
|
+
self.reloadCommentCount();
|
4732
|
+
});
|
4733
|
+
}, Mizuho);
|
4734
|
+
|
4735
|
+
Mizuho.reloadCommentCount = $.proxy(function() {
|
4736
|
+
this.callJuviaApi('list_topics.jsonp', {
|
4737
|
+
site_key: JUVIA_SITE_KEY,
|
4738
|
+
jsonp : 'Mizuho.topicListReceived'
|
4739
|
+
});
|
4740
|
+
}, Mizuho);
|
4741
|
+
|
4742
|
+
Mizuho.topicListReceived = $.proxy(function(result) {
|
4743
|
+
var self = this;
|
4744
|
+
var i, topic, map = {};
|
4745
|
+
for (i = 0; i < result.topics.length; i++) {
|
4746
|
+
topic = result.topics[i];
|
4747
|
+
map[topic.key] = topic;
|
4748
|
+
}
|
4749
|
+
|
4750
|
+
this.commentBalloons.each(function() {
|
4751
|
+
var info = self.getCommentThreadInfo(this);
|
4752
|
+
if (info) {
|
4753
|
+
topic = map[info.topic];
|
4754
|
+
if (topic) {
|
4755
|
+
var balloon = $(this);
|
4756
|
+
$('.count', balloon).text(topic.comment_count);
|
4757
|
+
balloon.removeClass('empty');
|
4758
|
+
balloon.addClass('nonempty');
|
4759
|
+
balloon.attr('title', null);
|
4760
|
+
}
|
4761
|
+
}
|
4762
|
+
});
|
4763
|
+
}, Mizuho);
|
4764
|
+
|
4765
|
+
$(document).ready(Mizuho.initializeCommenting);
|
4766
|
+
|
4767
|
+
</script>
|
4768
|
+
</body>
|
4769
|
+
</html>
|