passenger 2.0.3 → 2.0.4

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.

Files changed (275) hide show
  1. data/Rakefile +8 -5
  2. data/bin/passenger-install-apache2-module +6 -1
  3. data/doc/ApplicationPool algorithm.txt +23 -5
  4. data/doc/Architectural overview.html +778 -0
  5. data/doc/Security of user switching support.html +1 -1
  6. data/doc/Users guide.html +113 -31
  7. data/doc/Users guide.txt +104 -10
  8. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +683 -0
  9. data/doc/cxxapi/ApplicationPool_8h-source.html +224 -0
  10. data/doc/cxxapi/Application_8h-source.html +448 -0
  11. data/doc/cxxapi/Bucket_8h-source.html +61 -0
  12. data/doc/cxxapi/Configuration_8h-source.html +195 -0
  13. data/doc/cxxapi/DummySpawnManager_8h-source.html +126 -0
  14. data/doc/cxxapi/Exceptions_8h-source.html +244 -0
  15. data/doc/cxxapi/Hooks_8h-source.html +63 -0
  16. data/doc/cxxapi/Logging_8h-source.html +136 -0
  17. data/doc/cxxapi/MessageChannel_8h-source.html +524 -0
  18. data/doc/cxxapi/SpawnManager_8h-source.html +593 -0
  19. data/doc/cxxapi/StandardApplicationPool_8h-source.html +732 -0
  20. data/doc/cxxapi/System_8h-source.html +251 -0
  21. data/doc/cxxapi/Utils_8h-source.html +283 -0
  22. data/doc/cxxapi/annotated.html +59 -0
  23. data/doc/cxxapi/classClient-members.html +35 -0
  24. data/doc/cxxapi/classClient.html +117 -0
  25. data/doc/cxxapi/classDirectoryMapper-members.html +38 -0
  26. data/doc/cxxapi/classDirectoryMapper.html +203 -0
  27. data/doc/cxxapi/classHooks-members.html +33 -0
  28. data/doc/cxxapi/classHooks.html +43 -0
  29. data/doc/cxxapi/classPassenger_1_1Application-members.html +38 -0
  30. data/doc/cxxapi/classPassenger_1_1Application.html +229 -0
  31. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +41 -0
  32. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +359 -0
  33. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +36 -0
  34. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +225 -0
  35. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -0
  36. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -0
  37. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  38. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +43 -0
  39. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +329 -0
  40. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +33 -0
  41. data/doc/cxxapi/classPassenger_1_1BusyException.html +47 -0
  42. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +33 -0
  43. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +44 -0
  44. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +33 -0
  45. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +51 -0
  46. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +33 -0
  47. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +51 -0
  48. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -0
  49. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -0
  50. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +38 -0
  52. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +61 -0
  53. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -0
  54. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -0
  55. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  56. data/doc/cxxapi/classPassenger_1_1IOException-members.html +33 -0
  57. data/doc/cxxapi/classPassenger_1_1IOException.html +54 -0
  58. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -0
  59. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -0
  60. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  61. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +47 -0
  62. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +591 -0
  63. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +35 -0
  64. data/doc/cxxapi/classPassenger_1_1SpawnException.html +77 -0
  65. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +37 -0
  66. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +255 -0
  67. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +43 -0
  68. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +400 -0
  69. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -0
  70. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -0
  71. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  72. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +37 -0
  73. data/doc/cxxapi/classPassenger_1_1SystemException.html +154 -0
  74. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -0
  75. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -0
  76. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  77. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +36 -0
  78. data/doc/cxxapi/classPassenger_1_1TempFile.html +128 -0
  79. data/doc/cxxapi/classPassenger_1_1Thread-members.html +35 -0
  80. data/doc/cxxapi/classPassenger_1_1Thread.html +100 -0
  81. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption-members.html +33 -0
  82. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +46 -0
  83. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption-members.html +33 -0
  84. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption.html +44 -0
  85. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +33 -0
  86. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +44 -0
  87. data/doc/cxxapi/definitions_8h-source.html +28 -0
  88. data/doc/cxxapi/doxygen.css +433 -0
  89. data/doc/cxxapi/doxygen.png +0 -0
  90. data/doc/cxxapi/files.html +42 -0
  91. data/doc/cxxapi/ftv2blank.png +0 -0
  92. data/doc/cxxapi/ftv2doc.png +0 -0
  93. data/doc/cxxapi/ftv2folderclosed.png +0 -0
  94. data/doc/cxxapi/ftv2folderopen.png +0 -0
  95. data/doc/cxxapi/ftv2lastnode.png +0 -0
  96. data/doc/cxxapi/ftv2link.png +0 -0
  97. data/doc/cxxapi/ftv2mlastnode.png +0 -0
  98. data/doc/cxxapi/ftv2mnode.png +0 -0
  99. data/doc/cxxapi/ftv2node.png +0 -0
  100. data/doc/cxxapi/ftv2plastnode.png +0 -0
  101. data/doc/cxxapi/ftv2pnode.png +0 -0
  102. data/doc/cxxapi/ftv2vertline.png +0 -0
  103. data/doc/cxxapi/functions.html +215 -0
  104. data/doc/cxxapi/functions_func.html +210 -0
  105. data/doc/cxxapi/functions_type.html +46 -0
  106. data/doc/cxxapi/functions_vars.html +48 -0
  107. data/doc/cxxapi/graph_legend.dot +22 -0
  108. data/doc/cxxapi/graph_legend.html +87 -0
  109. data/doc/cxxapi/graph_legend.png +0 -0
  110. data/doc/cxxapi/group__Configuration.html +236 -0
  111. data/doc/cxxapi/group__Configuration.png +0 -0
  112. data/doc/cxxapi/group__Core.html +51 -0
  113. data/doc/cxxapi/group__Core.png +0 -0
  114. data/doc/cxxapi/group__Exceptions.html +43 -0
  115. data/doc/cxxapi/group__Hooks.html +46 -0
  116. data/doc/cxxapi/group__Hooks.png +0 -0
  117. data/doc/cxxapi/group__Support.html +406 -0
  118. data/doc/cxxapi/hierarchy.html +67 -0
  119. data/doc/cxxapi/index.html +11 -0
  120. data/doc/cxxapi/inherit__graph__0.map +1 -0
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -0
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -0
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -0
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -0
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -0
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -0
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -0
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -0
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -0
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -0
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -0
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -0
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -0
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -0
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -0
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -0
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -0
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -0
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -0
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -0
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -0
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +2 -0
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -0
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -0
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -0
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +1 -0
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -0
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -0
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -0
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -0
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -0
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -0
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -0
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -0
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -0
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +1 -0
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -0
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -0
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -0
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -0
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -0
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +2 -0
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -0
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +102 -0
  187. data/doc/cxxapi/main.html +27 -0
  188. data/doc/cxxapi/modules.html +34 -0
  189. data/doc/cxxapi/namespacePassenger.html +208 -0
  190. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +43 -0
  191. data/doc/cxxapi/namespacemembers.html +70 -0
  192. data/doc/cxxapi/namespacemembers_func.html +66 -0
  193. data/doc/cxxapi/namespacemembers_type.html +46 -0
  194. data/doc/cxxapi/namespaces.html +35 -0
  195. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +33 -0
  196. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +49 -0
  197. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +33 -0
  198. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +49 -0
  199. data/doc/cxxapi/tab_b.gif +0 -0
  200. data/doc/cxxapi/tab_l.gif +0 -0
  201. data/doc/cxxapi/tab_r.gif +0 -0
  202. data/doc/cxxapi/tabs.css +102 -0
  203. data/doc/cxxapi/tree.html +167 -0
  204. data/doc/rdoc/classes/ConditionVariable.html +160 -0
  205. data/doc/rdoc/classes/Exception.html +120 -0
  206. data/doc/rdoc/classes/GC.html +113 -0
  207. data/doc/rdoc/classes/IO.html +150 -0
  208. data/doc/rdoc/classes/Passenger.html +136 -0
  209. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +402 -0
  210. data/doc/rdoc/classes/Passenger/AbstractServer.html +649 -0
  211. data/doc/rdoc/classes/Passenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  212. data/doc/rdoc/classes/Passenger/AbstractServer/ServerError.html +96 -0
  213. data/doc/rdoc/classes/Passenger/AbstractServer/ServerNotStarted.html +97 -0
  214. data/doc/rdoc/classes/Passenger/AbstractServer/UnknownMessage.html +96 -0
  215. data/doc/rdoc/classes/Passenger/AppInitError.html +137 -0
  216. data/doc/rdoc/classes/Passenger/Application.html +298 -0
  217. data/doc/rdoc/classes/Passenger/ConsoleTextTemplate.html +172 -0
  218. data/doc/rdoc/classes/Passenger/FrameworkInitError.html +143 -0
  219. data/doc/rdoc/classes/Passenger/HTMLTemplate.html +175 -0
  220. data/doc/rdoc/classes/Passenger/InitializationError.html +141 -0
  221. data/doc/rdoc/classes/Passenger/MessageChannel.html +488 -0
  222. data/doc/rdoc/classes/Passenger/NativeSupport.html +320 -0
  223. data/doc/rdoc/classes/Passenger/SpawnManager.html +375 -0
  224. data/doc/rdoc/classes/Passenger/UnknownError.html +125 -0
  225. data/doc/rdoc/classes/Passenger/Utils.html +578 -0
  226. data/doc/rdoc/classes/Passenger/VersionNotFound.html +140 -0
  227. data/doc/rdoc/classes/PlatformInfo.html +302 -0
  228. data/doc/rdoc/classes/RakeExtensions.html +197 -0
  229. data/doc/rdoc/created.rid +1 -0
  230. data/doc/rdoc/files/DEVELOPERS_TXT.html +230 -0
  231. data/doc/rdoc/files/README.html +150 -0
  232. data/doc/rdoc/files/ext/passenger/native_support_c.html +92 -0
  233. data/doc/rdoc/files/lib/passenger/abstract_request_handler_rb.html +126 -0
  234. data/doc/rdoc/files/lib/passenger/abstract_server_rb.html +127 -0
  235. data/doc/rdoc/files/lib/passenger/application_rb.html +123 -0
  236. data/doc/rdoc/files/lib/passenger/console_text_template_rb.html +122 -0
  237. data/doc/rdoc/files/lib/passenger/constants_rb.html +114 -0
  238. data/doc/rdoc/files/lib/passenger/dependencies_rb.html +130 -0
  239. data/doc/rdoc/files/lib/passenger/exceptions_rb.html +118 -0
  240. data/doc/rdoc/files/lib/passenger/html_template_rb.html +122 -0
  241. data/doc/rdoc/files/lib/passenger/message_channel_rb.html +118 -0
  242. data/doc/rdoc/files/lib/passenger/platform_info_rb.html +122 -0
  243. data/doc/rdoc/files/lib/passenger/simple_benchmarking_rb.html +118 -0
  244. data/doc/rdoc/files/lib/passenger/spawn_manager_rb.html +139 -0
  245. data/doc/rdoc/files/lib/passenger/utils_rb.html +130 -0
  246. data/doc/rdoc/files/lib/rake/extensions_rb.html +122 -0
  247. data/doc/rdoc/fr_class_index.html +71 -0
  248. data/doc/rdoc/fr_file_index.html +63 -0
  249. data/doc/rdoc/fr_method_index.html +120 -0
  250. data/doc/rdoc/index.html +26 -0
  251. data/doc/rdoc/rdoc-style.css +187 -0
  252. data/ext/apache2/ApplicationPool.h +12 -0
  253. data/ext/apache2/ApplicationPoolServer.h +6 -0
  254. data/ext/apache2/ApplicationPoolServerExecutable.cpp +6 -0
  255. data/ext/apache2/Bucket.cpp +63 -69
  256. data/ext/apache2/Bucket.h +2 -0
  257. data/ext/apache2/Configuration.cpp +24 -0
  258. data/ext/apache2/Configuration.h +16 -1
  259. data/ext/apache2/Hooks.cpp +5 -3
  260. data/ext/apache2/StandardApplicationPool.h +30 -11
  261. data/lib/passenger/abstract_request_handler.rb +3 -0
  262. data/lib/passenger/abstract_server.rb +3 -3
  263. data/lib/passenger/application.rb +4 -2
  264. data/lib/passenger/dependencies.rb +10 -1
  265. data/lib/passenger/platform_info.rb +40 -1
  266. data/lib/passenger/rack/request_handler.rb +4 -2
  267. data/lib/passenger/railz/application_spawner.rb +7 -1
  268. data/lib/passenger/utils.rb +6 -8
  269. data/lib/rake/gempackagetask.rb +0 -6
  270. data/lib/rake/rdoctask.rb +84 -23
  271. data/test/ApplicationPoolTest.cpp +36 -0
  272. data/test/ruby/rails/minimal_spawner_spec.rb +8 -0
  273. data/test/ruby/utils_spec.rb +33 -0
  274. data/test/stub/rails_apps/foobar/config/environments/production.rb +0 -1
  275. metadata +262 -5
@@ -0,0 +1,732 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
3
+ <title>Passenger: StandardApplicationPool.h Source File</title>
4
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
5
+ <link href="tabs.css" rel="stylesheet" type="text/css">
6
+ </head><body>
7
+ <!-- Generated by Doxygen 1.5.5 -->
8
+ <div class="navigation" id="top">
9
+ <div class="tabs">
10
+ <ul>
11
+ <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
12
+ <li><a href="modules.html"><span>Modules</span></a></li>
13
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
14
+ <li><a href="annotated.html"><span>Classes</span></a></li>
15
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
16
+ </ul>
17
+ </div>
18
+ <h1>StandardApplicationPool.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
19
+ <a name="l00002"></a>00002 <span class="comment"> * Phusion Passenger - http://www.modrails.com/</span>
20
+ <a name="l00003"></a>00003 <span class="comment"> * Copyright (C) 2008 Phusion</span>
21
+ <a name="l00004"></a>00004 <span class="comment"> *</span>
22
+ <a name="l00005"></a>00005 <span class="comment"> * Phusion Passenger is a trademark of Hongli Lai &amp; Ninh Bui.</span>
23
+ <a name="l00006"></a>00006 <span class="comment"> *</span>
24
+ <a name="l00007"></a>00007 <span class="comment"> * This program is free software; you can redistribute it and/or modify</span>
25
+ <a name="l00008"></a>00008 <span class="comment"> * it under the terms of the GNU General Public License as published by</span>
26
+ <a name="l00009"></a>00009 <span class="comment"> * the Free Software Foundation; version 2 of the License.</span>
27
+ <a name="l00010"></a>00010 <span class="comment"> *</span>
28
+ <a name="l00011"></a>00011 <span class="comment"> * This program is distributed in the hope that it will be useful,</span>
29
+ <a name="l00012"></a>00012 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
30
+ <a name="l00013"></a>00013 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
31
+ <a name="l00014"></a>00014 <span class="comment"> * GNU General Public License for more details.</span>
32
+ <a name="l00015"></a>00015 <span class="comment"> *</span>
33
+ <a name="l00016"></a>00016 <span class="comment"> * You should have received a copy of the GNU General Public License along</span>
34
+ <a name="l00017"></a>00017 <span class="comment"> * with this program; if not, write to the Free Software Foundation, Inc.,</span>
35
+ <a name="l00018"></a>00018 <span class="comment"> * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span>
36
+ <a name="l00019"></a>00019 <span class="comment"> */</span>
37
+ <a name="l00020"></a>00020 <span class="preprocessor">#ifndef _PASSENGER_STANDARD_APPLICATION_POOL_H_</span>
38
+ <a name="l00021"></a>00021 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_STANDARD_APPLICATION_POOL_H_</span>
39
+ <a name="l00022"></a>00022 <span class="preprocessor"></span>
40
+ <a name="l00023"></a>00023 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
41
+ <a name="l00024"></a>00024 <span class="preprocessor">#include &lt;boost/weak_ptr.hpp&gt;</span>
42
+ <a name="l00025"></a>00025 <span class="preprocessor">#include &lt;boost/thread.hpp&gt;</span>
43
+ <a name="l00026"></a>00026 <span class="preprocessor">#include &lt;boost/bind.hpp&gt;</span>
44
+ <a name="l00027"></a>00027 <span class="preprocessor">#include &lt;boost/date_time/microsec_time_clock.hpp&gt;</span>
45
+ <a name="l00028"></a>00028 <span class="preprocessor">#include &lt;boost/date_time/posix_time/posix_time.hpp&gt;</span>
46
+ <a name="l00029"></a>00029
47
+ <a name="l00030"></a>00030 <span class="preprocessor">#include &lt;string&gt;</span>
48
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;sstream&gt;</span>
49
+ <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;map&gt;</span>
50
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &lt;list&gt;</span>
51
+ <a name="l00034"></a>00034
52
+ <a name="l00035"></a>00035 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
53
+ <a name="l00036"></a>00036 <span class="preprocessor">#include &lt;sys/stat.h&gt;</span>
54
+ <a name="l00037"></a>00037 <span class="preprocessor">#include &lt;stdio.h&gt;</span>
55
+ <a name="l00038"></a>00038 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
56
+ <a name="l00039"></a>00039 <span class="preprocessor">#include &lt;ctime&gt;</span>
57
+ <a name="l00040"></a>00040 <span class="preprocessor">#include &lt;cerrno&gt;</span>
58
+ <a name="l00041"></a>00041 <span class="preprocessor">#ifdef TESTING_APPLICATION_POOL</span>
59
+ <a name="l00042"></a>00042 <span class="preprocessor"></span><span class="preprocessor"> #include &lt;cstdlib&gt;</span>
60
+ <a name="l00043"></a>00043 <span class="preprocessor">#endif</span>
61
+ <a name="l00044"></a>00044 <span class="preprocessor"></span>
62
+ <a name="l00045"></a>00045 <span class="preprocessor">#include "ApplicationPool.h"</span>
63
+ <a name="l00046"></a>00046 <span class="preprocessor">#include "Logging.h"</span>
64
+ <a name="l00047"></a>00047 <span class="preprocessor">#include "System.h"</span>
65
+ <a name="l00048"></a>00048 <span class="preprocessor">#ifdef PASSENGER_USE_DUMMY_SPAWN_MANAGER</span>
66
+ <a name="l00049"></a>00049 <span class="preprocessor"></span><span class="preprocessor"> #include "DummySpawnManager.h"</span>
67
+ <a name="l00050"></a>00050 <span class="preprocessor">#else</span>
68
+ <a name="l00051"></a>00051 <span class="preprocessor"></span><span class="preprocessor"> #include "SpawnManager.h"</span>
69
+ <a name="l00052"></a>00052 <span class="preprocessor">#endif</span>
70
+ <a name="l00053"></a>00053 <span class="preprocessor"></span>
71
+ <a name="l00054"></a>00054 <span class="keyword">namespace </span>Passenger {
72
+ <a name="l00055"></a>00055
73
+ <a name="l00056"></a>00056 <span class="keyword">using namespace </span>std;
74
+ <a name="l00057"></a>00057 <span class="keyword">using namespace </span>boost;
75
+ <a name="l00058"></a>00058
76
+ <a name="l00059"></a>00059 <span class="keyword">class </span>ApplicationPoolServer;
77
+ <a name="l00060"></a>00060
78
+ <a name="l00061"></a>00061 <span class="comment">/****************************************************************</span>
79
+ <a name="l00062"></a>00062 <span class="comment"> *</span>
80
+ <a name="l00063"></a>00063 <span class="comment"> * See "doc/ApplicationPool algorithm.txt" for a more readable</span>
81
+ <a name="l00064"></a>00064 <span class="comment"> * and detailed description of the algorithm implemented here.</span>
82
+ <a name="l00065"></a>00065 <span class="comment"> *</span>
83
+ <a name="l00066"></a>00066 <span class="comment"> ****************************************************************/</span>
84
+ <a name="l00067"></a>00067 <span class="comment"></span>
85
+ <a name="l00068"></a>00068 <span class="comment">/**</span>
86
+ <a name="l00069"></a>00069 <span class="comment"> * A standard implementation of ApplicationPool for single-process environments.</span>
87
+ <a name="l00070"></a>00070 <span class="comment"> *</span>
88
+ <a name="l00071"></a>00071 <span class="comment"> * The environment may or may not be multithreaded - StandardApplicationPool is completely</span>
89
+ <a name="l00072"></a>00072 <span class="comment"> * thread-safe. Apache with the threading MPM is an example of a multithreaded single-process</span>
90
+ <a name="l00073"></a>00073 <span class="comment"> * environment.</span>
91
+ <a name="l00074"></a>00074 <span class="comment"> *</span>
92
+ <a name="l00075"></a>00075 <span class="comment"> * This class is unusable in multi-process environments such as Apache with the prefork MPM.</span>
93
+ <a name="l00076"></a>00076 <span class="comment"> * The reasons are as follows:</span>
94
+ <a name="l00077"></a>00077 <span class="comment"> * - StandardApplicationPool uses threads internally. Because threads disappear after a fork(),</span>
95
+ <a name="l00078"></a>00078 <span class="comment"> * a StandardApplicationPool object will become unusable after a fork().</span>
96
+ <a name="l00079"></a>00079 <span class="comment"> * - StandardApplicationPool stores its internal cache on the heap. Different processes</span>
97
+ <a name="l00080"></a>00080 <span class="comment"> * cannot share their heaps, so they will not be able to access each others' pool cache.</span>
98
+ <a name="l00081"></a>00081 <span class="comment"> * - StandardApplicationPool has a connection to the spawn server. If there are multiple</span>
99
+ <a name="l00082"></a>00082 <span class="comment"> * processes, and they all use the spawn servers's connection at the same time without</span>
100
+ <a name="l00083"></a>00083 <span class="comment"> * some sort of synchronization, then bad things will happen.</span>
101
+ <a name="l00084"></a>00084 <span class="comment"> *</span>
102
+ <a name="l00085"></a>00085 <span class="comment"> * (Of course, StandardApplicationPool &lt;em&gt;is&lt;/em&gt; usable if each process creates its own</span>
103
+ <a name="l00086"></a>00086 <span class="comment"> * StandardApplicationPool object, but that would defeat the point of having a shared pool.)</span>
104
+ <a name="l00087"></a>00087 <span class="comment"> *</span>
105
+ <a name="l00088"></a>00088 <span class="comment"> * For multi-process environments, one should use ApplicationPoolServer instead.</span>
106
+ <a name="l00089"></a>00089 <span class="comment"> *</span>
107
+ <a name="l00090"></a>00090 <span class="comment"> * @ingroup Support</span>
108
+ <a name="l00091"></a>00091 <span class="comment"> */</span>
109
+ <a name="l00092"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html">00092</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1StandardApplicationPool.html" title="A standard implementation of ApplicationPool for single-process environments.">StandardApplicationPool</a>: <span class="keyword">public</span> <a class="code" href="classPassenger_1_1ApplicationPool.html" title="A persistent pool of Applications.">ApplicationPool</a> {
110
+ <a name="l00093"></a>00093 <span class="keyword">private</span>:
111
+ <a name="l00094"></a>00094 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_IDLE_TIME = 120;
112
+ <a name="l00095"></a>00095 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_POOL_SIZE = 20;
113
+ <a name="l00096"></a>00096 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_INSTANCES_PER_APP = 0;
114
+ <a name="l00097"></a>00097 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> CLEANER_THREAD_STACK_SIZE = 1024 * 128;
115
+ <a name="l00098"></a>00098 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> MAX_GET_ATTEMPTS = 10;
116
+ <a name="l00099"></a>00099 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> GET_TIMEOUT = 5000; <span class="comment">// In milliseconds.</span>
117
+ <a name="l00100"></a>00100
118
+ <a name="l00101"></a>00101 <span class="keyword">friend</span> <span class="keyword">class </span><a class="code" href="classPassenger_1_1ApplicationPoolServer.html" title="Multi-process usage support for ApplicationPool.">ApplicationPoolServer</a>;
119
+ <a name="l00102"></a>00102 <span class="keyword">struct </span>AppContainer;
120
+ <a name="l00103"></a>00103
121
+ <a name="l00104"></a>00104 <span class="keyword">typedef</span> shared_ptr&lt;AppContainer&gt; AppContainerPtr;
122
+ <a name="l00105"></a>00105 <span class="keyword">typedef</span> list&lt;AppContainerPtr&gt; AppContainerList;
123
+ <a name="l00106"></a>00106 <span class="keyword">typedef</span> shared_ptr&lt;AppContainerList&gt; AppContainerListPtr;
124
+ <a name="l00107"></a>00107 <span class="keyword">typedef</span> map&lt;string, AppContainerListPtr&gt; ApplicationMap;
125
+ <a name="l00108"></a>00108
126
+ <a name="l00109"></a>00109 <span class="keyword">struct </span>AppContainer {
127
+ <a name="l00110"></a>00110 <a class="code" href="namespacePassenger.html#6a15fd5e8765802a0b8b077e15297e18" title="Convenient alias for Application smart pointer.">ApplicationPtr</a> app;
128
+ <a name="l00111"></a>00111 time_t lastUsed;
129
+ <a name="l00112"></a>00112 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> sessions;
130
+ <a name="l00113"></a>00113 AppContainerList::iterator iterator;
131
+ <a name="l00114"></a>00114 AppContainerList::iterator ia_iterator;
132
+ <a name="l00115"></a>00115 };
133
+ <a name="l00116"></a>00116
134
+ <a name="l00117"></a>00117 <span class="keyword">struct </span>SharedData {
135
+ <a name="l00118"></a>00118 mutex lock;
136
+ <a name="l00119"></a>00119 condition activeOrMaxChanged;
137
+ <a name="l00120"></a>00120
138
+ <a name="l00121"></a>00121 ApplicationMap apps;
139
+ <a name="l00122"></a>00122 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max;
140
+ <a name="l00123"></a>00123 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count;
141
+ <a name="l00124"></a>00124 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> active;
142
+ <a name="l00125"></a>00125 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxPerApp;
143
+ <a name="l00126"></a>00126 AppContainerList inactiveApps;
144
+ <a name="l00127"></a>00127 map&lt;string, time_t&gt; restartFileTimes;
145
+ <a name="l00128"></a>00128 map&lt;string, unsigned int&gt; appInstanceCount;
146
+ <a name="l00129"></a>00129 };
147
+ <a name="l00130"></a>00130
148
+ <a name="l00131"></a>00131 <span class="keyword">typedef</span> shared_ptr&lt;SharedData&gt; SharedDataPtr;
149
+ <a name="l00132"></a>00132
150
+ <a name="l00133"></a>00133 <span class="keyword">struct </span>SessionCloseCallback {
151
+ <a name="l00134"></a>00134 SharedDataPtr data;
152
+ <a name="l00135"></a>00135 weak_ptr&lt;AppContainer&gt; container;
153
+ <a name="l00136"></a>00136
154
+ <a name="l00137"></a>00137 SessionCloseCallback(SharedDataPtr data,
155
+ <a name="l00138"></a>00138 <span class="keyword">const</span> weak_ptr&lt;AppContainer&gt; &amp;container) {
156
+ <a name="l00139"></a>00139 this-&gt;data = data;
157
+ <a name="l00140"></a>00140 this-&gt;container = container;
158
+ <a name="l00141"></a>00141 }
159
+ <a name="l00142"></a>00142
160
+ <a name="l00143"></a>00143 <span class="keywordtype">void</span> operator()() {
161
+ <a name="l00144"></a>00144 mutex::scoped_lock l(data-&gt;lock);
162
+ <a name="l00145"></a>00145 AppContainerPtr container(this-&gt;container.lock());
163
+ <a name="l00146"></a>00146
164
+ <a name="l00147"></a>00147 <span class="keywordflow">if</span> (container == NULL) {
165
+ <a name="l00148"></a>00148 <span class="keywordflow">return</span>;
166
+ <a name="l00149"></a>00149 }
167
+ <a name="l00150"></a>00150
168
+ <a name="l00151"></a>00151 ApplicationMap::iterator it;
169
+ <a name="l00152"></a>00152 it = data-&gt;apps.find(container-&gt;app-&gt;getAppRoot());
170
+ <a name="l00153"></a>00153 <span class="keywordflow">if</span> (it != data-&gt;apps.end()) {
171
+ <a name="l00154"></a>00154 AppContainerListPtr list(it-&gt;second);
172
+ <a name="l00155"></a>00155 container-&gt;lastUsed = time(NULL);
173
+ <a name="l00156"></a>00156 container-&gt;sessions--;
174
+ <a name="l00157"></a>00157 <span class="keywordflow">if</span> (container-&gt;sessions == 0) {
175
+ <a name="l00158"></a>00158 list-&gt;erase(container-&gt;iterator);
176
+ <a name="l00159"></a>00159 list-&gt;push_front(container);
177
+ <a name="l00160"></a>00160 container-&gt;iterator = list-&gt;begin();
178
+ <a name="l00161"></a>00161 data-&gt;inactiveApps.push_back(container);
179
+ <a name="l00162"></a>00162 container-&gt;ia_iterator = data-&gt;inactiveApps.end();
180
+ <a name="l00163"></a>00163 container-&gt;ia_iterator--;
181
+ <a name="l00164"></a>00164 data-&gt;active--;
182
+ <a name="l00165"></a>00165 data-&gt;activeOrMaxChanged.notify_all();
183
+ <a name="l00166"></a>00166 }
184
+ <a name="l00167"></a>00167 }
185
+ <a name="l00168"></a>00168 }
186
+ <a name="l00169"></a>00169 };
187
+ <a name="l00170"></a>00170
188
+ <a name="l00171"></a>00171 <span class="preprocessor"> #ifdef PASSENGER_USE_DUMMY_SPAWN_MANAGER</span>
189
+ <a name="l00172"></a>00172 <span class="preprocessor"></span> <a class="code" href="classPassenger_1_1DummySpawnManager.html" title="A dummy SpawnManager replacement for testing/debugging purposes.">DummySpawnManager</a> spawnManager;
190
+ <a name="l00173"></a>00173 <span class="preprocessor"> #else</span>
191
+ <a name="l00174"></a>00174 <span class="preprocessor"></span> <a class="code" href="classPassenger_1_1SpawnManager.html" title="Spawning of Ruby on Rails/Rack application instances.">SpawnManager</a> spawnManager;
192
+ <a name="l00175"></a>00175 <span class="preprocessor"> #endif</span>
193
+ <a name="l00176"></a>00176 <span class="preprocessor"></span> SharedDataPtr data;
194
+ <a name="l00177"></a>00177 thread *cleanerThread;
195
+ <a name="l00178"></a>00178 <span class="keywordtype">bool</span> detached;
196
+ <a name="l00179"></a>00179 <span class="keywordtype">bool</span> done;
197
+ <a name="l00180"></a>00180 <span class="keywordtype">bool</span> useGlobalQueue;
198
+ <a name="l00181"></a>00181 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxIdleTime;
199
+ <a name="l00182"></a>00182 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> waitingOnGlobalQueue;
200
+ <a name="l00183"></a>00183 condition cleanerThreadSleeper;
201
+ <a name="l00184"></a>00184
202
+ <a name="l00185"></a>00185 <span class="comment">// Shortcuts for instance variables in SharedData. Saves typing in get().</span>
203
+ <a name="l00186"></a>00186 mutex &amp;lock;
204
+ <a name="l00187"></a>00187 condition &amp;activeOrMaxChanged;
205
+ <a name="l00188"></a>00188 ApplicationMap &amp;apps;
206
+ <a name="l00189"></a>00189 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;max;
207
+ <a name="l00190"></a>00190 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;count;
208
+ <a name="l00191"></a>00191 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;active;
209
+ <a name="l00192"></a>00192 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;maxPerApp;
210
+ <a name="l00193"></a>00193 AppContainerList &amp;inactiveApps;
211
+ <a name="l00194"></a>00194 map&lt;string, time_t&gt; &amp;restartFileTimes;
212
+ <a name="l00195"></a>00195 map&lt;string, unsigned int&gt; &amp;appInstanceCount;
213
+ <a name="l00196"></a>00196 <span class="comment"></span>
214
+ <a name="l00197"></a>00197 <span class="comment"> /**</span>
215
+ <a name="l00198"></a>00198 <span class="comment"> * Verify that all the invariants are correct.</span>
216
+ <a name="l00199"></a>00199 <span class="comment"> */</span>
217
+ <a name="l00200"></a>00200 <span class="keywordtype">bool</span> <span class="keyword">inline</span> verifyState() {
218
+ <a name="l00201"></a>00201 <span class="preprocessor"> #if PASSENGER_DEBUG</span>
219
+ <a name="l00202"></a>00202 <span class="preprocessor"></span> <span class="comment">// Invariant for _apps_.</span>
220
+ <a name="l00203"></a>00203 ApplicationMap::const_iterator it;
221
+ <a name="l00204"></a>00204 <span class="keywordflow">for</span> (it = apps.begin(); it != apps.end(); it++) {
222
+ <a name="l00205"></a>00205 AppContainerList *list = it-&gt;second.get();
223
+ <a name="l00206"></a>00206 P_ASSERT(!list-&gt;empty(), <span class="keyword">false</span>, <span class="stringliteral">"List for '"</span> &lt;&lt; it-&gt;first &lt;&lt; <span class="stringliteral">"' is nonempty."</span>);
224
+ <a name="l00207"></a>00207
225
+ <a name="l00208"></a>00208 AppContainerList::const_iterator prev_lit;
226
+ <a name="l00209"></a>00209 AppContainerList::const_iterator lit;
227
+ <a name="l00210"></a>00210 prev_lit = list-&gt;begin();
228
+ <a name="l00211"></a>00211 lit = prev_lit;
229
+ <a name="l00212"></a>00212 lit++;
230
+ <a name="l00213"></a>00213 <span class="keywordflow">for</span> (; lit != list-&gt;end(); lit++) {
231
+ <a name="l00214"></a>00214 <span class="keywordflow">if</span> ((*prev_lit)-&gt;sessions &gt; 0) {
232
+ <a name="l00215"></a>00215 P_ASSERT((*lit)-&gt;sessions &gt; 0, <span class="keyword">false</span>,
233
+ <a name="l00216"></a>00216 <span class="stringliteral">"List for '"</span> &lt;&lt; it-&gt;first &lt;&lt;
234
+ <a name="l00217"></a>00217 <span class="stringliteral">"' is sorted from nonactive to active"</span>);
235
+ <a name="l00218"></a>00218 }
236
+ <a name="l00219"></a>00219 }
237
+ <a name="l00220"></a>00220 }
238
+ <a name="l00221"></a>00221
239
+ <a name="l00222"></a>00222 P_ASSERT(active &lt;= count, <span class="keyword">false</span>,
240
+ <a name="l00223"></a>00223 <span class="stringliteral">"active ("</span> &lt;&lt; active &lt;&lt; <span class="stringliteral">") &lt; count ("</span> &lt;&lt; count &lt;&lt; <span class="stringliteral">")"</span>);
241
+ <a name="l00224"></a>00224 P_ASSERT(inactiveApps.size() == count - active, <span class="keyword">false</span>,
242
+ <a name="l00225"></a>00225 <span class="stringliteral">"inactive_apps.size() == count - active"</span>);
243
+ <a name="l00226"></a>00226 <span class="preprocessor"> #endif</span>
244
+ <a name="l00227"></a>00227 <span class="preprocessor"></span> <span class="keywordflow">return</span> <span class="keyword">true</span>;
245
+ <a name="l00228"></a>00228 }
246
+ <a name="l00229"></a>00229
247
+ <a name="l00230"></a>00230 <span class="keyword">template</span>&lt;<span class="keyword">typename</span> LockActionType&gt;
248
+ <a name="l00231"></a>00231 <span class="keywordtype">string</span> toString(LockActionType lockAction)<span class="keyword"> const </span>{
249
+ <a name="l00232"></a>00232 unique_lock&lt;mutex&gt; l(lock, lockAction);
250
+ <a name="l00233"></a>00233 stringstream result;
251
+ <a name="l00234"></a>00234
252
+ <a name="l00235"></a>00235 result &lt;&lt; <span class="stringliteral">"----------- General information -----------"</span> &lt;&lt; endl;
253
+ <a name="l00236"></a>00236 result &lt;&lt; <span class="stringliteral">"max = "</span> &lt;&lt; max &lt;&lt; endl;
254
+ <a name="l00237"></a>00237 result &lt;&lt; <span class="stringliteral">"count = "</span> &lt;&lt; count &lt;&lt; endl;
255
+ <a name="l00238"></a>00238 result &lt;&lt; <span class="stringliteral">"active = "</span> &lt;&lt; active &lt;&lt; endl;
256
+ <a name="l00239"></a>00239 result &lt;&lt; <span class="stringliteral">"inactive = "</span> &lt;&lt; inactiveApps.size() &lt;&lt; endl;
257
+ <a name="l00240"></a>00240 result &lt;&lt; <span class="stringliteral">"Using global queue: "</span> &lt;&lt; (useGlobalQueue ? <span class="stringliteral">"yes"</span> : <span class="stringliteral">"no"</span>) &lt;&lt; endl;
258
+ <a name="l00241"></a>00241 result &lt;&lt; <span class="stringliteral">"Waiting on global queue: "</span> &lt;&lt; waitingOnGlobalQueue &lt;&lt; endl;
259
+ <a name="l00242"></a>00242 result &lt;&lt; endl;
260
+ <a name="l00243"></a>00243
261
+ <a name="l00244"></a>00244 result &lt;&lt; <span class="stringliteral">"----------- Applications -----------"</span> &lt;&lt; endl;
262
+ <a name="l00245"></a>00245 ApplicationMap::const_iterator it;
263
+ <a name="l00246"></a>00246 <span class="keywordflow">for</span> (it = apps.begin(); it != apps.end(); it++) {
264
+ <a name="l00247"></a>00247 AppContainerList *list = it-&gt;second.get();
265
+ <a name="l00248"></a>00248 AppContainerList::const_iterator lit;
266
+ <a name="l00249"></a>00249
267
+ <a name="l00250"></a>00250 result &lt;&lt; it-&gt;first &lt;&lt; <span class="stringliteral">": "</span> &lt;&lt; endl;
268
+ <a name="l00251"></a>00251 <span class="keywordflow">for</span> (lit = list-&gt;begin(); lit != list-&gt;end(); lit++) {
269
+ <a name="l00252"></a>00252 AppContainer *container = lit-&gt;get();
270
+ <a name="l00253"></a>00253 <span class="keywordtype">char</span> buf[128];
271
+ <a name="l00254"></a>00254
272
+ <a name="l00255"></a>00255 snprintf(buf, <span class="keyword">sizeof</span>(buf), <span class="stringliteral">"PID: %-8d Sessions: %d"</span>,
273
+ <a name="l00256"></a>00256 container-&gt;app-&gt;getPid(), container-&gt;sessions);
274
+ <a name="l00257"></a>00257 result &lt;&lt; <span class="stringliteral">" "</span> &lt;&lt; buf &lt;&lt; endl;
275
+ <a name="l00258"></a>00258 }
276
+ <a name="l00259"></a>00259 result &lt;&lt; endl;
277
+ <a name="l00260"></a>00260 }
278
+ <a name="l00261"></a>00261 <span class="keywordflow">return</span> result.str();
279
+ <a name="l00262"></a>00262 }
280
+ <a name="l00263"></a>00263
281
+ <a name="l00264"></a>00264 <span class="keywordtype">bool</span> needsRestart(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot) {
282
+ <a name="l00265"></a>00265 <span class="keywordtype">string</span> restartFile(appRoot);
283
+ <a name="l00266"></a>00266 restartFile.append(<span class="stringliteral">"/tmp/restart.txt"</span>);
284
+ <a name="l00267"></a>00267
285
+ <a name="l00268"></a>00268 <span class="keyword">struct </span>stat buf;
286
+ <a name="l00269"></a>00269 <span class="keywordtype">bool</span> result;
287
+ <a name="l00270"></a>00270 <span class="keywordtype">int</span> ret;
288
+ <a name="l00271"></a>00271
289
+ <a name="l00272"></a>00272 <span class="keywordflow">do</span> {
290
+ <a name="l00273"></a>00273 ret = stat(restartFile.c_str(), &amp;buf);
291
+ <a name="l00274"></a>00274 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
292
+ <a name="l00275"></a>00275 <span class="keywordflow">if</span> (ret == 0) {
293
+ <a name="l00276"></a>00276 <span class="keywordflow">do</span> {
294
+ <a name="l00277"></a>00277 ret = unlink(restartFile.c_str());
295
+ <a name="l00278"></a>00278 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; (errno == EINTR || errno == EAGAIN));
296
+ <a name="l00279"></a>00279 <span class="keywordflow">if</span> (ret == 0 || errno == ENOENT) {
297
+ <a name="l00280"></a>00280 restartFileTimes.erase(appRoot);
298
+ <a name="l00281"></a>00281 result = <span class="keyword">true</span>;
299
+ <a name="l00282"></a>00282 } <span class="keywordflow">else</span> {
300
+ <a name="l00283"></a>00283 map&lt;string, time_t&gt;::const_iterator it;
301
+ <a name="l00284"></a>00284
302
+ <a name="l00285"></a>00285 it = restartFileTimes.find(appRoot);
303
+ <a name="l00286"></a>00286 <span class="keywordflow">if</span> (it == restartFileTimes.end()) {
304
+ <a name="l00287"></a>00287 result = <span class="keyword">true</span>;
305
+ <a name="l00288"></a>00288 } <span class="keywordflow">else</span> {
306
+ <a name="l00289"></a>00289 result = buf.st_mtime != restartFileTimes[appRoot];
307
+ <a name="l00290"></a>00290 }
308
+ <a name="l00291"></a>00291 restartFileTimes[appRoot] = buf.st_mtime;
309
+ <a name="l00292"></a>00292 }
310
+ <a name="l00293"></a>00293 } <span class="keywordflow">else</span> {
311
+ <a name="l00294"></a>00294 restartFileTimes.erase(appRoot);
312
+ <a name="l00295"></a>00295 result = <span class="keyword">false</span>;
313
+ <a name="l00296"></a>00296 }
314
+ <a name="l00297"></a>00297 <span class="keywordflow">return</span> result;
315
+ <a name="l00298"></a>00298 }
316
+ <a name="l00299"></a>00299
317
+ <a name="l00300"></a>00300 <span class="keywordtype">void</span> cleanerThreadMainLoop() {
318
+ <a name="l00301"></a>00301 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
319
+ <a name="l00302"></a>00302 unique_lock&lt;mutex&gt; l(lock);
320
+ <a name="l00303"></a>00303 <span class="keywordflow">try</span> {
321
+ <a name="l00304"></a>00304 <span class="keywordflow">while</span> (!done &amp;&amp; !this_thread::interruption_requested()) {
322
+ <a name="l00305"></a>00305 xtime xt;
323
+ <a name="l00306"></a>00306 xtime_get(&amp;xt, TIME_UTC);
324
+ <a name="l00307"></a>00307 xt.sec += maxIdleTime + 1;
325
+ <a name="l00308"></a>00308 <span class="keywordflow">if</span> (cleanerThreadSleeper.timed_wait(l, xt)) {
326
+ <a name="l00309"></a>00309 <span class="comment">// Condition was woken up.</span>
327
+ <a name="l00310"></a>00310 <span class="keywordflow">if</span> (done) {
328
+ <a name="l00311"></a>00311 <span class="comment">// StandardApplicationPool is being destroyed.</span>
329
+ <a name="l00312"></a>00312 <span class="keywordflow">break</span>;
330
+ <a name="l00313"></a>00313 } <span class="keywordflow">else</span> {
331
+ <a name="l00314"></a>00314 <span class="comment">// maxIdleTime changed.</span>
332
+ <a name="l00315"></a>00315 <span class="keywordflow">continue</span>;
333
+ <a name="l00316"></a>00316 }
334
+ <a name="l00317"></a>00317 }
335
+ <a name="l00318"></a>00318
336
+ <a name="l00319"></a>00319 time_t now = InterruptableCalls::time(NULL);
337
+ <a name="l00320"></a>00320 AppContainerList::iterator it;
338
+ <a name="l00321"></a>00321 <span class="keywordflow">for</span> (it = inactiveApps.begin(); it != inactiveApps.end(); it++) {
339
+ <a name="l00322"></a>00322 AppContainer &amp;container(*it-&gt;get());
340
+ <a name="l00323"></a>00323 <a class="code" href="namespacePassenger.html#6a15fd5e8765802a0b8b077e15297e18" title="Convenient alias for Application smart pointer.">ApplicationPtr</a> app(container.app);
341
+ <a name="l00324"></a>00324 AppContainerListPtr appList(apps[app-&gt;getAppRoot()]);
342
+ <a name="l00325"></a>00325
343
+ <a name="l00326"></a>00326 <span class="keywordflow">if</span> (now - container.lastUsed &gt; (time_t) maxIdleTime) {
344
+ <a name="l00327"></a>00327 P_DEBUG(<span class="stringliteral">"Cleaning idle app "</span> &lt;&lt; app-&gt;getAppRoot() &lt;&lt;
345
+ <a name="l00328"></a>00328 <span class="stringliteral">" (PID "</span> &lt;&lt; app-&gt;getPid() &lt;&lt; <span class="stringliteral">")"</span>);
346
+ <a name="l00329"></a>00329 appList-&gt;erase(container.iterator);
347
+ <a name="l00330"></a>00330
348
+ <a name="l00331"></a>00331 AppContainerList::iterator prev = it;
349
+ <a name="l00332"></a>00332 prev--;
350
+ <a name="l00333"></a>00333 inactiveApps.erase(it);
351
+ <a name="l00334"></a>00334 it = prev;
352
+ <a name="l00335"></a>00335
353
+ <a name="l00336"></a>00336 appInstanceCount[app-&gt;getAppRoot()]--;
354
+ <a name="l00337"></a>00337
355
+ <a name="l00338"></a>00338 count--;
356
+ <a name="l00339"></a>00339 }
357
+ <a name="l00340"></a>00340 <span class="keywordflow">if</span> (appList-&gt;empty()) {
358
+ <a name="l00341"></a>00341 apps.erase(app-&gt;getAppRoot());
359
+ <a name="l00342"></a>00342 appInstanceCount.erase(app-&gt;getAppRoot());
360
+ <a name="l00343"></a>00343 data-&gt;restartFileTimes.erase(app-&gt;getAppRoot());
361
+ <a name="l00344"></a>00344 }
362
+ <a name="l00345"></a>00345 }
363
+ <a name="l00346"></a>00346 }
364
+ <a name="l00347"></a>00347 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
365
+ <a name="l00348"></a>00348 P_ERROR(<span class="stringliteral">"Uncaught exception: "</span> &lt;&lt; e.what());
366
+ <a name="l00349"></a>00349 }
367
+ <a name="l00350"></a>00350 }
368
+ <a name="l00351"></a>00351 <span class="comment"></span>
369
+ <a name="l00352"></a>00352 <span class="comment"> /**</span>
370
+ <a name="l00353"></a>00353 <span class="comment"> * @throws boost::thread_interrupted</span>
371
+ <a name="l00354"></a>00354 <span class="comment"> * @throws SpawnException</span>
372
+ <a name="l00355"></a>00355 <span class="comment"> * @throws SystemException</span>
373
+ <a name="l00356"></a>00356 <span class="comment"> */</span>
374
+ <a name="l00357"></a>00357 pair&lt;AppContainerPtr, AppContainerList *&gt;
375
+ <a name="l00358"></a>00358 spawnOrUseExisting(
376
+ <a name="l00359"></a>00359 mutex::scoped_lock &amp;l,
377
+ <a name="l00360"></a>00360 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot,
378
+ <a name="l00361"></a>00361 <span class="keywordtype">bool</span> lowerPrivilege,
379
+ <a name="l00362"></a>00362 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser,
380
+ <a name="l00363"></a>00363 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment,
381
+ <a name="l00364"></a>00364 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnMethod,
382
+ <a name="l00365"></a>00365 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appType
383
+ <a name="l00366"></a>00366 ) {
384
+ <a name="l00367"></a>00367 beginning_of_function:
385
+ <a name="l00368"></a>00368
386
+ <a name="l00369"></a>00369 this_thread::disable_interruption di;
387
+ <a name="l00370"></a>00370 <a class="code" href="classboost_1_1this__thread_1_1disable__syscall__interruption.html" title="Create this struct on the stack to temporarily disable system call interruption,...">this_thread::disable_syscall_interruption</a> dsi;
388
+ <a name="l00371"></a>00371 AppContainerPtr container;
389
+ <a name="l00372"></a>00372 AppContainerList *list;
390
+ <a name="l00373"></a>00373
391
+ <a name="l00374"></a>00374 <span class="keywordflow">try</span> {
392
+ <a name="l00375"></a>00375 ApplicationMap::iterator it(apps.find(appRoot));
393
+ <a name="l00376"></a>00376
394
+ <a name="l00377"></a>00377 <span class="keywordflow">if</span> (it != apps.end() &amp;&amp; needsRestart(appRoot)) {
395
+ <a name="l00378"></a>00378 AppContainerList::iterator it2;
396
+ <a name="l00379"></a>00379 list = it-&gt;second.get();
397
+ <a name="l00380"></a>00380 <span class="keywordflow">for</span> (it2 = list-&gt;begin(); it2 != list-&gt;end(); it2++) {
398
+ <a name="l00381"></a>00381 container = *it2;
399
+ <a name="l00382"></a>00382 <span class="keywordflow">if</span> (container-&gt;sessions == 0) {
400
+ <a name="l00383"></a>00383 inactiveApps.erase(container-&gt;ia_iterator);
401
+ <a name="l00384"></a>00384 } <span class="keywordflow">else</span> {
402
+ <a name="l00385"></a>00385 active--;
403
+ <a name="l00386"></a>00386 }
404
+ <a name="l00387"></a>00387 it2--;
405
+ <a name="l00388"></a>00388 list-&gt;erase(container-&gt;iterator);
406
+ <a name="l00389"></a>00389 count--;
407
+ <a name="l00390"></a>00390 }
408
+ <a name="l00391"></a>00391 apps.erase(appRoot);
409
+ <a name="l00392"></a>00392 appInstanceCount.erase(appRoot);
410
+ <a name="l00393"></a>00393 spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#2e85c43042b9556ca2fd74b8d28956ce" title="Remove the cached application instances at the given application root.">reload</a>(appRoot);
411
+ <a name="l00394"></a>00394 it = apps.end();
412
+ <a name="l00395"></a>00395 activeOrMaxChanged.notify_all();
413
+ <a name="l00396"></a>00396 }
414
+ <a name="l00397"></a>00397
415
+ <a name="l00398"></a>00398 <span class="keywordflow">if</span> (it != apps.end()) {
416
+ <a name="l00399"></a>00399 list = it-&gt;second.get();
417
+ <a name="l00400"></a>00400
418
+ <a name="l00401"></a>00401 <span class="keywordflow">if</span> (list-&gt;front()-&gt;sessions == 0) {
419
+ <a name="l00402"></a>00402 container = list-&gt;front();
420
+ <a name="l00403"></a>00403 list-&gt;pop_front();
421
+ <a name="l00404"></a>00404 list-&gt;push_back(container);
422
+ <a name="l00405"></a>00405 container-&gt;iterator = list-&gt;end();
423
+ <a name="l00406"></a>00406 container-&gt;iterator--;
424
+ <a name="l00407"></a>00407 inactiveApps.erase(container-&gt;ia_iterator);
425
+ <a name="l00408"></a>00408 active++;
426
+ <a name="l00409"></a>00409 activeOrMaxChanged.notify_all();
427
+ <a name="l00410"></a>00410 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (count &gt;= max || (
428
+ <a name="l00411"></a>00411 maxPerApp != 0 &amp;&amp; appInstanceCount[appRoot] &gt;= maxPerApp )
429
+ <a name="l00412"></a>00412 ) {
430
+ <a name="l00413"></a>00413 <span class="keywordflow">if</span> (useGlobalQueue) {
431
+ <a name="l00414"></a>00414 waitingOnGlobalQueue++;
432
+ <a name="l00415"></a>00415 activeOrMaxChanged.wait(l);
433
+ <a name="l00416"></a>00416 waitingOnGlobalQueue--;
434
+ <a name="l00417"></a>00417 <span class="keywordflow">goto</span> beginning_of_function;
435
+ <a name="l00418"></a>00418 } <span class="keywordflow">else</span> {
436
+ <a name="l00419"></a>00419 AppContainerList::iterator it(list-&gt;begin());
437
+ <a name="l00420"></a>00420 AppContainerList::iterator smallest(list-&gt;begin());
438
+ <a name="l00421"></a>00421 it++;
439
+ <a name="l00422"></a>00422 <span class="keywordflow">for</span> (; it != list-&gt;end(); it++) {
440
+ <a name="l00423"></a>00423 <span class="keywordflow">if</span> ((*it)-&gt;sessions &lt; (*smallest)-&gt;sessions) {
441
+ <a name="l00424"></a>00424 smallest = it;
442
+ <a name="l00425"></a>00425 }
443
+ <a name="l00426"></a>00426 }
444
+ <a name="l00427"></a>00427 container = *smallest;
445
+ <a name="l00428"></a>00428 list-&gt;erase(smallest);
446
+ <a name="l00429"></a>00429 list-&gt;push_back(container);
447
+ <a name="l00430"></a>00430 container-&gt;iterator = list-&gt;end();
448
+ <a name="l00431"></a>00431 container-&gt;iterator--;
449
+ <a name="l00432"></a>00432 }
450
+ <a name="l00433"></a>00433 } <span class="keywordflow">else</span> {
451
+ <a name="l00434"></a>00434 container = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> AppContainer());
452
+ <a name="l00435"></a>00435 {
453
+ <a name="l00436"></a>00436 this_thread::restore_interruption ri(di);
454
+ <a name="l00437"></a>00437 <a class="code" href="classboost_1_1this__thread_1_1restore__syscall__interruption.html" title="Creating an object of this class on the stack will restore the system call interruption...">this_thread::restore_syscall_interruption</a> rsi(dsi);
455
+ <a name="l00438"></a>00438 container-&gt;app = spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#1bafa97204ea49a88b66272be3377d53" title="Spawn a new instance of a Ruby on Rails or Rack application.">spawn</a>(appRoot,
456
+ <a name="l00439"></a>00439 lowerPrivilege, lowestUser, environment,
457
+ <a name="l00440"></a>00440 spawnMethod, appType);
458
+ <a name="l00441"></a>00441 }
459
+ <a name="l00442"></a>00442 container-&gt;sessions = 0;
460
+ <a name="l00443"></a>00443 list-&gt;push_back(container);
461
+ <a name="l00444"></a>00444 container-&gt;iterator = list-&gt;end();
462
+ <a name="l00445"></a>00445 container-&gt;iterator--;
463
+ <a name="l00446"></a>00446 appInstanceCount[appRoot]++;
464
+ <a name="l00447"></a>00447 count++;
465
+ <a name="l00448"></a>00448 active++;
466
+ <a name="l00449"></a>00449 activeOrMaxChanged.notify_all();
467
+ <a name="l00450"></a>00450 }
468
+ <a name="l00451"></a>00451 } <span class="keywordflow">else</span> {
469
+ <a name="l00452"></a>00452 <span class="keywordflow">while</span> (!(
470
+ <a name="l00453"></a>00453 active &lt; max &amp;&amp;
471
+ <a name="l00454"></a>00454 (maxPerApp == 0 || appInstanceCount[appRoot] &lt; maxPerApp)
472
+ <a name="l00455"></a>00455 )) {
473
+ <a name="l00456"></a>00456 activeOrMaxChanged.wait(l);
474
+ <a name="l00457"></a>00457 }
475
+ <a name="l00458"></a>00458 <span class="keywordflow">if</span> (count == max) {
476
+ <a name="l00459"></a>00459 container = inactiveApps.front();
477
+ <a name="l00460"></a>00460 inactiveApps.pop_front();
478
+ <a name="l00461"></a>00461 list = apps[container-&gt;app-&gt;getAppRoot()].get();
479
+ <a name="l00462"></a>00462 list-&gt;erase(container-&gt;iterator);
480
+ <a name="l00463"></a>00463 <span class="keywordflow">if</span> (list-&gt;empty()) {
481
+ <a name="l00464"></a>00464 apps.erase(container-&gt;app-&gt;getAppRoot());
482
+ <a name="l00465"></a>00465 restartFileTimes.erase(container-&gt;app-&gt;getAppRoot());
483
+ <a name="l00466"></a>00466 appInstanceCount.erase(container-&gt;app-&gt;getAppRoot());
484
+ <a name="l00467"></a>00467 } <span class="keywordflow">else</span> {
485
+ <a name="l00468"></a>00468 appInstanceCount[container-&gt;app-&gt;getAppRoot()]--;
486
+ <a name="l00469"></a>00469 }
487
+ <a name="l00470"></a>00470 count--;
488
+ <a name="l00471"></a>00471 }
489
+ <a name="l00472"></a>00472 container = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> AppContainer());
490
+ <a name="l00473"></a>00473 {
491
+ <a name="l00474"></a>00474 this_thread::restore_interruption ri(di);
492
+ <a name="l00475"></a>00475 <a class="code" href="classboost_1_1this__thread_1_1restore__syscall__interruption.html" title="Creating an object of this class on the stack will restore the system call interruption...">this_thread::restore_syscall_interruption</a> rsi(dsi);
493
+ <a name="l00476"></a>00476 container-&gt;app = spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#1bafa97204ea49a88b66272be3377d53" title="Spawn a new instance of a Ruby on Rails or Rack application.">spawn</a>(appRoot, lowerPrivilege, lowestUser,
494
+ <a name="l00477"></a>00477 environment, spawnMethod, appType);
495
+ <a name="l00478"></a>00478 }
496
+ <a name="l00479"></a>00479 container-&gt;sessions = 0;
497
+ <a name="l00480"></a>00480 it = apps.find(appRoot);
498
+ <a name="l00481"></a>00481 <span class="keywordflow">if</span> (it == apps.end()) {
499
+ <a name="l00482"></a>00482 list = <span class="keyword">new</span> AppContainerList();
500
+ <a name="l00483"></a>00483 apps[appRoot] = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(list);
501
+ <a name="l00484"></a>00484 appInstanceCount[appRoot] = 1;
502
+ <a name="l00485"></a>00485 } <span class="keywordflow">else</span> {
503
+ <a name="l00486"></a>00486 list = it-&gt;second.get();
504
+ <a name="l00487"></a>00487 appInstanceCount[appRoot]++;
505
+ <a name="l00488"></a>00488 }
506
+ <a name="l00489"></a>00489 list-&gt;push_back(container);
507
+ <a name="l00490"></a>00490 container-&gt;iterator = list-&gt;end();
508
+ <a name="l00491"></a>00491 container-&gt;iterator--;
509
+ <a name="l00492"></a>00492 count++;
510
+ <a name="l00493"></a>00493 active++;
511
+ <a name="l00494"></a>00494 activeOrMaxChanged.notify_all();
512
+ <a name="l00495"></a>00495 }
513
+ <a name="l00496"></a>00496 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a> &amp;e) {
514
+ <a name="l00497"></a>00497 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
515
+ <a name="l00498"></a>00498 message.append(appRoot);
516
+ <a name="l00499"></a>00499 message.append(<span class="stringliteral">"': "</span>);
517
+ <a name="l00500"></a>00500 message.append(e.<a class="code" href="classPassenger_1_1SpawnException.html#d2da180f89a43423a4b37248249972ff">what</a>());
518
+ <a name="l00501"></a>00501 <span class="keywordflow">if</span> (e.<a class="code" href="classPassenger_1_1SpawnException.html#e65dc272e183fd9e5637a4091cc6bbf4" title="Check whether an error page is available.">hasErrorPage</a>()) {
519
+ <a name="l00502"></a>00502 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a>(message, e.<a class="code" href="classPassenger_1_1SpawnException.html#6f675a37edd7070875d0744e7dd010a1" title="Return the error page content.">getErrorPage</a>());
520
+ <a name="l00503"></a>00503 } <span class="keywordflow">else</span> {
521
+ <a name="l00504"></a>00504 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a>(message);
522
+ <a name="l00505"></a>00505 }
523
+ <a name="l00506"></a>00506 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
524
+ <a name="l00507"></a>00507 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
525
+ <a name="l00508"></a>00508 message.append(appRoot);
526
+ <a name="l00509"></a>00509 message.append(<span class="stringliteral">"': "</span>);
527
+ <a name="l00510"></a>00510 message.append(e.what());
528
+ <a name="l00511"></a>00511 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SpawnException.html" title="Thrown when SpawnManager or ApplicationPool fails to spawn an application instance...">SpawnException</a>(message);
529
+ <a name="l00512"></a>00512 }
530
+ <a name="l00513"></a>00513
531
+ <a name="l00514"></a>00514 <span class="keywordflow">return</span> make_pair(container, list);
532
+ <a name="l00515"></a>00515 }
533
+ <a name="l00516"></a>00516
534
+ <a name="l00517"></a>00517 <span class="keyword">public</span>:<span class="comment"></span>
535
+ <a name="l00518"></a>00518 <span class="comment"> /**</span>
536
+ <a name="l00519"></a>00519 <span class="comment"> * Create a new StandardApplicationPool object.</span>
537
+ <a name="l00520"></a>00520 <span class="comment"> *</span>
538
+ <a name="l00521"></a>00521 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
539
+ <a name="l00522"></a>00522 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
540
+ <a name="l00523"></a>00523 <span class="comment"> * Messages on its standard output and standard error channels</span>
541
+ <a name="l00524"></a>00524 <span class="comment"> * will be written to this log file. If an empty string is</span>
542
+ <a name="l00525"></a>00525 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
543
+ <a name="l00526"></a>00526 <span class="comment"> * will use the same standard output/error channels as the</span>
544
+ <a name="l00527"></a>00527 <span class="comment"> * current process.</span>
545
+ <a name="l00528"></a>00528 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
546
+ <a name="l00529"></a>00529 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
547
+ <a name="l00530"></a>00530 <span class="comment"> * parameter only has effect if the current process is</span>
548
+ <a name="l00531"></a>00531 <span class="comment"> * running as root. If the empty string is given, or if</span>
549
+ <a name="l00532"></a>00532 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
550
+ <a name="l00533"></a>00533 <span class="comment"> * the spawn manager will be run as the current user.</span>
551
+ <a name="l00534"></a>00534 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
552
+ <a name="l00535"></a>00535 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server.</span>
553
+ <a name="l00536"></a>00536 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
554
+ <a name="l00537"></a>00537 <span class="comment"> */</span>
555
+ <a name="l00538"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#f175704fc477f37ba1d387be09fa2e6b">00538</a> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#f175704fc477f37ba1d387be09fa2e6b" title="Create a new StandardApplicationPool object.">StandardApplicationPool</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnServerCommand,
556
+ <a name="l00539"></a>00539 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
557
+ <a name="l00540"></a>00540 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
558
+ <a name="l00541"></a>00541 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
559
+ <a name="l00542"></a>00542 :
560
+ <a name="l00543"></a>00543 #ifndef PASSENGER_USE_DUMMY_SPAWN_MANAGER
561
+ <a name="l00544"></a>00544 spawnManager(spawnServerCommand, logFile, rubyCommand, user),
562
+ <a name="l00545"></a>00545 #endif
563
+ <a name="l00546"></a>00546 data(new SharedData()),
564
+ <a name="l00547"></a>00547 lock(data-&gt;lock),
565
+ <a name="l00548"></a>00548 activeOrMaxChanged(data-&gt;activeOrMaxChanged),
566
+ <a name="l00549"></a>00549 apps(data-&gt;apps),
567
+ <a name="l00550"></a>00550 max(data-&gt;max),
568
+ <a name="l00551"></a>00551 count(data-&gt;count),
569
+ <a name="l00552"></a>00552 active(data-&gt;active),
570
+ <a name="l00553"></a>00553 maxPerApp(data-&gt;maxPerApp),
571
+ <a name="l00554"></a>00554 inactiveApps(data-&gt;inactiveApps),
572
+ <a name="l00555"></a>00555 restartFileTimes(data-&gt;restartFileTimes),
573
+ <a name="l00556"></a>00556 appInstanceCount(data-&gt;appInstanceCount)
574
+ <a name="l00557"></a>00557 {
575
+ <a name="l00558"></a>00558 detached = <span class="keyword">false</span>;
576
+ <a name="l00559"></a>00559 done = <span class="keyword">false</span>;
577
+ <a name="l00560"></a>00560 max = DEFAULT_MAX_POOL_SIZE;
578
+ <a name="l00561"></a>00561 count = 0;
579
+ <a name="l00562"></a>00562 active = 0;
580
+ <a name="l00563"></a>00563 useGlobalQueue = <span class="keyword">false</span>;
581
+ <a name="l00564"></a>00564 waitingOnGlobalQueue = 0;
582
+ <a name="l00565"></a>00565 maxPerApp = DEFAULT_MAX_INSTANCES_PER_APP;
583
+ <a name="l00566"></a>00566 maxIdleTime = DEFAULT_MAX_IDLE_TIME;
584
+ <a name="l00567"></a>00567 cleanerThread = <span class="keyword">new</span> thread(
585
+ <a name="l00568"></a>00568 bind(&amp;StandardApplicationPool::cleanerThreadMainLoop, <span class="keyword">this</span>),
586
+ <a name="l00569"></a>00569 CLEANER_THREAD_STACK_SIZE
587
+ <a name="l00570"></a>00570 );
588
+ <a name="l00571"></a>00571 }
589
+ <a name="l00572"></a>00572
590
+ <a name="l00573"></a>00573 <span class="keyword">virtual</span> ~<a class="code" href="classPassenger_1_1StandardApplicationPool.html" title="A standard implementation of ApplicationPool for single-process environments.">StandardApplicationPool</a>() {
591
+ <a name="l00574"></a>00574 <span class="keywordflow">if</span> (!detached) {
592
+ <a name="l00575"></a>00575 this_thread::disable_interruption di;
593
+ <a name="l00576"></a>00576 {
594
+ <a name="l00577"></a>00577 mutex::scoped_lock l(lock);
595
+ <a name="l00578"></a>00578 done = <span class="keyword">true</span>;
596
+ <a name="l00579"></a>00579 cleanerThreadSleeper.notify_one();
597
+ <a name="l00580"></a>00580 }
598
+ <a name="l00581"></a>00581 cleanerThread-&gt;join();
599
+ <a name="l00582"></a>00582 }
600
+ <a name="l00583"></a>00583 <span class="keyword">delete</span> cleanerThread;
601
+ <a name="l00584"></a>00584 }
602
+ <a name="l00585"></a>00585
603
+ <a name="l00586"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#0dcdd88c39d7f1a1d667e24c3cb9b243">00586</a> <span class="keyword">virtual</span> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a> <span class="keyword">get</span>(
604
+ <a name="l00587"></a>00587 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot,
605
+ <a name="l00588"></a>00588 <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
606
+ <a name="l00589"></a>00589 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>,
607
+ <a name="l00590"></a>00590 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
608
+ <a name="l00591"></a>00591 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnMethod = <span class="stringliteral">"smart"</span>,
609
+ <a name="l00592"></a>00592 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appType = <span class="stringliteral">"rails"</span>
610
+ <a name="l00593"></a>00593 ) {
611
+ <a name="l00594"></a>00594 <span class="keyword">using namespace </span>boost::posix_time;
612
+ <a name="l00595"></a>00595 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> attempt = 0;
613
+ <a name="l00596"></a>00596 ptime timeLimit(get_system_time() + millisec(GET_TIMEOUT));
614
+ <a name="l00597"></a>00597 unique_lock&lt;mutex&gt; l(lock);
615
+ <a name="l00598"></a>00598
616
+ <a name="l00599"></a>00599 <span class="keywordflow">while</span> (<span class="keyword">true</span>) {
617
+ <a name="l00600"></a>00600 attempt++;
618
+ <a name="l00601"></a>00601
619
+ <a name="l00602"></a>00602 pair&lt;AppContainerPtr, AppContainerList *&gt; p(
620
+ <a name="l00603"></a>00603 spawnOrUseExisting(l, appRoot, lowerPrivilege, lowestUser,
621
+ <a name="l00604"></a>00604 environment, spawnMethod, appType)
622
+ <a name="l00605"></a>00605 );
623
+ <a name="l00606"></a>00606 AppContainerPtr &amp;container(p.first);
624
+ <a name="l00607"></a>00607 AppContainerList &amp;list(*p.second);
625
+ <a name="l00608"></a>00608
626
+ <a name="l00609"></a>00609 container-&gt;lastUsed = time(NULL);
627
+ <a name="l00610"></a>00610 container-&gt;sessions++;
628
+ <a name="l00611"></a>00611
629
+ <a name="l00612"></a>00612 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
630
+ <a name="l00613"></a>00613 <span class="stringliteral">"State is valid:\n"</span> &lt;&lt; <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(<span class="keyword">false</span>));
631
+ <a name="l00614"></a>00614 <span class="keywordflow">try</span> {
632
+ <a name="l00615"></a>00615 <span class="keywordflow">return</span> container-&gt;app-&gt;connect(SessionCloseCallback(data, container));
633
+ <a name="l00616"></a>00616 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
634
+ <a name="l00617"></a>00617 container-&gt;sessions--;
635
+ <a name="l00618"></a>00618 <span class="keywordflow">if</span> (attempt == MAX_GET_ATTEMPTS) {
636
+ <a name="l00619"></a>00619 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot connect to an existing "</span>
637
+ <a name="l00620"></a>00620 <span class="stringliteral">"application instance for '"</span>);
638
+ <a name="l00621"></a>00621 message.append(appRoot);
639
+ <a name="l00622"></a>00622 message.append(<span class="stringliteral">"': "</span>);
640
+ <a name="l00623"></a>00623 <span class="keywordflow">try</span> {
641
+ <a name="l00624"></a>00624 <span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;syse =
642
+ <a name="l00625"></a>00625 <span class="keyword">dynamic_cast&lt;</span><span class="keyword">const </span><a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;<span class="keyword">&gt;</span>(e);
643
+ <a name="l00626"></a>00626 message.append(syse.<a class="code" href="classPassenger_1_1SystemException.html#0ef41d755fea2c9b1db2252e7c418dc8" title="Returns the system&amp;#39;s error message.">sys</a>());
644
+ <a name="l00627"></a>00627 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> bad_cast &amp;) {
645
+ <a name="l00628"></a>00628 message.append(e.what());
646
+ <a name="l00629"></a>00629 }
647
+ <a name="l00630"></a>00630 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(message);
648
+ <a name="l00631"></a>00631 } <span class="keywordflow">else</span> {
649
+ <a name="l00632"></a>00632 list.erase(container-&gt;iterator);
650
+ <a name="l00633"></a>00633 <span class="keywordflow">if</span> (list.empty()) {
651
+ <a name="l00634"></a>00634 apps.erase(appRoot);
652
+ <a name="l00635"></a>00635 appInstanceCount.erase(appRoot);
653
+ <a name="l00636"></a>00636 }
654
+ <a name="l00637"></a>00637 count--;
655
+ <a name="l00638"></a>00638 active--;
656
+ <a name="l00639"></a>00639 activeOrMaxChanged.notify_all();
657
+ <a name="l00640"></a>00640 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
658
+ <a name="l00641"></a>00641 <span class="stringliteral">"State is valid."</span>);
659
+ <a name="l00642"></a>00642 }
660
+ <a name="l00643"></a>00643 }
661
+ <a name="l00644"></a>00644 }
662
+ <a name="l00645"></a>00645 <span class="comment">// Never reached; shut up compiler warning</span>
663
+ <a name="l00646"></a>00646 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>();
664
+ <a name="l00647"></a>00647 }
665
+ <a name="l00648"></a>00648
666
+ <a name="l00649"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#bcf8faeb4f431ae07ea0e20270661d08">00649</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#bcf8faeb4f431ae07ea0e20270661d08" title="Clear all application instances that are currently in the pool.">clear</a>() {
667
+ <a name="l00650"></a>00650 mutex::scoped_lock l(lock);
668
+ <a name="l00651"></a>00651 apps.clear();
669
+ <a name="l00652"></a>00652 inactiveApps.clear();
670
+ <a name="l00653"></a>00653 restartFileTimes.clear();
671
+ <a name="l00654"></a>00654 appInstanceCount.clear();
672
+ <a name="l00655"></a>00655 count = 0;
673
+ <a name="l00656"></a>00656 active = 0;
674
+ <a name="l00657"></a>00657 }
675
+ <a name="l00658"></a>00658
676
+ <a name="l00659"></a>00659 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
677
+ <a name="l00660"></a>00660 mutex::scoped_lock l(lock);
678
+ <a name="l00661"></a>00661 maxIdleTime = seconds;
679
+ <a name="l00662"></a>00662 cleanerThreadSleeper.notify_one();
680
+ <a name="l00663"></a>00663 }
681
+ <a name="l00664"></a>00664
682
+ <a name="l00665"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#04ef8c92da189520ad2022f4f82e9553">00665</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#04ef8c92da189520ad2022f4f82e9553" title="Set a hard limit on the number of application instances that this ApplicationPool...">setMax</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max) {
683
+ <a name="l00666"></a>00666 mutex::scoped_lock l(lock);
684
+ <a name="l00667"></a>00667 this-&gt;max = max;
685
+ <a name="l00668"></a>00668 activeOrMaxChanged.notify_all();
686
+ <a name="l00669"></a>00669 }
687
+ <a name="l00670"></a>00670
688
+ <a name="l00671"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#7773c4a3dfbd88eac72401d063831788">00671</a> <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#7773c4a3dfbd88eac72401d063831788" title="Get the number of active applications in the pool.">getActive</a>()<span class="keyword"> const </span>{
689
+ <a name="l00672"></a>00672 <span class="keywordflow">return</span> active;
690
+ <a name="l00673"></a>00673 }
691
+ <a name="l00674"></a>00674
692
+ <a name="l00675"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#cdbfe2b9ffacdab4438c879c2411bf02">00675</a> <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#cdbfe2b9ffacdab4438c879c2411bf02" title="Get the number of active applications in the pool.">getCount</a>()<span class="keyword"> const </span>{
693
+ <a name="l00676"></a>00676 <span class="keywordflow">return</span> count;
694
+ <a name="l00677"></a>00677 }
695
+ <a name="l00678"></a>00678
696
+ <a name="l00679"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#3bafcda8d880f70561ad8a9da16e26ef">00679</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#3bafcda8d880f70561ad8a9da16e26ef" title="Set a hard limit on the number of application instances that a single application...">setMaxPerApp</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxPerApp) {
697
+ <a name="l00680"></a>00680 mutex::scoped_lock l(lock);
698
+ <a name="l00681"></a>00681 this-&gt;maxPerApp = maxPerApp;
699
+ <a name="l00682"></a>00682 activeOrMaxChanged.notify_all();
700
+ <a name="l00683"></a>00683 }
701
+ <a name="l00684"></a>00684
702
+ <a name="l00685"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#e9c699b56f3a755ab10269c7fe585c2d">00685</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#e9c699b56f3a755ab10269c7fe585c2d" title="Sets whether to use a global queue instead of a per-backend process queue.">setUseGlobalQueue</a>(<span class="keywordtype">bool</span> value) {
703
+ <a name="l00686"></a>00686 this-&gt;useGlobalQueue = value;
704
+ <a name="l00687"></a>00687 }
705
+ <a name="l00688"></a>00688
706
+ <a name="l00689"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#6955152d237920988d20297d2fff5660">00689</a> <span class="keyword">virtual</span> pid_t <a class="code" href="classPassenger_1_1StandardApplicationPool.html#6955152d237920988d20297d2fff5660" title="Get the process ID of the spawn server that is used.">getSpawnServerPid</a>()<span class="keyword"> const </span>{
707
+ <a name="l00690"></a>00690 <span class="keywordflow">return</span> spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#1f77e2e7e6cb464028c13a29f983ad8e" title="Get the Process ID of the spawn server.">getServerPid</a>();
708
+ <a name="l00691"></a>00691 }
709
+ <a name="l00692"></a>00692 <span class="comment"></span>
710
+ <a name="l00693"></a>00693 <span class="comment"> /**</span>
711
+ <a name="l00694"></a>00694 <span class="comment"> * Returns a textual description of the internal state of</span>
712
+ <a name="l00695"></a>00695 <span class="comment"> * the application pool.</span>
713
+ <a name="l00696"></a>00696 <span class="comment"> */</span>
714
+ <a name="l00697"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383">00697</a> <span class="keyword">virtual</span> <span class="keywordtype">string</span> <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(<span class="keywordtype">bool</span> lockMutex = <span class="keyword">true</span>)<span class="keyword"> const </span>{
715
+ <a name="l00698"></a>00698 <span class="keywordflow">if</span> (lockMutex) {
716
+ <a name="l00699"></a>00699 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(boost::adopt_lock);
717
+ <a name="l00700"></a>00700 } <span class="keywordflow">else</span> {
718
+ <a name="l00701"></a>00701 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(boost::defer_lock);
719
+ <a name="l00702"></a>00702 }
720
+ <a name="l00703"></a>00703 }
721
+ <a name="l00704"></a>00704 };
722
+ <a name="l00705"></a>00705
723
+ <a name="l00706"></a>00706 } <span class="comment">// namespace Passenger</span>
724
+ <a name="l00707"></a>00707
725
+ <a name="l00708"></a>00708 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_STANDARD_APPLICATION_POOL_H_ */</span>
726
+ <a name="l00709"></a>00709
727
+ </pre></div></div>
728
+ <hr size="1"><address style="text-align: right;"><small>Generated on Mon Dec 1 14:27:22 2008 for Passenger by&nbsp;
729
+ <a href="http://www.doxygen.org/index.html">
730
+ <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
731
+ </body>
732
+ </html>