passenger 2.0.6 → 2.1.2

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 (497) hide show
  1. data/DEVELOPERS.TXT +10 -4
  2. data/LICENSE +1 -1
  3. data/NEWS +0 -0
  4. data/Rakefile +183 -117
  5. data/benchmark/dispatcher.rb +5 -9
  6. data/bin/passenger-install-apache2-module +52 -18
  7. data/bin/passenger-memory-stats +67 -13
  8. data/bin/passenger-spawn-server +8 -4
  9. data/bin/passenger-status +21 -46
  10. data/bin/passenger-stress-test +5 -5
  11. data/debian/postinst +1 -1
  12. data/doc/ApplicationPool algorithm.txt +180 -128
  13. data/doc/Architectural overview.html +1 -778
  14. data/doc/Security of user switching support.html +1 -643
  15. data/doc/Users guide Apache.html +3127 -0
  16. data/doc/Users guide Nginx.html +1458 -0
  17. data/doc/Users guide.html +1404 -467
  18. data/doc/Users guide.txt +843 -105
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +751 -641
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +168 -171
  21. data/doc/cxxapi/Application_8h-source.html +494 -394
  22. data/doc/cxxapi/Bucket_8h-source.html +21 -15
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +191 -0
  24. data/doc/cxxapi/Configuration_8h-source.html +311 -149
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +309 -0
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +3 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +182 -165
  28. data/doc/cxxapi/FileChecker_8h-source.html +130 -0
  29. data/doc/cxxapi/Hooks_8h-source.html +2 -3
  30. data/doc/cxxapi/Logging_8h-source.html +92 -89
  31. data/doc/cxxapi/MessageChannel_8h-source.html +585 -477
  32. data/doc/cxxapi/PoolOptions_8h-source.html +305 -0
  33. data/doc/cxxapi/SpawnManager_8h-source.html +515 -540
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +779 -679
  35. data/doc/cxxapi/SystemTime_8h-source.html +104 -0
  36. data/doc/cxxapi/Utils_8h-source.html +331 -227
  37. data/doc/cxxapi/annotated.html +6 -7
  38. data/doc/cxxapi/classClient-members.html +1 -2
  39. data/doc/cxxapi/classClient.html +1 -2
  40. data/doc/cxxapi/classHooks-members.html +5 -2
  41. data/doc/cxxapi/classHooks.html +112 -2
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +2 -3
  43. data/doc/cxxapi/classPassenger_1_1Application.html +8 -9
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +42 -81
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -2
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +3 -4
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  49. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +3 -2
  50. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +74 -3
  51. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -2
  52. data/doc/cxxapi/classPassenger_1_1BusyException.html +2 -3
  53. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -2
  54. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +2 -3
  55. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +38 -0
  56. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +256 -0
  57. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -2
  58. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +2 -3
  59. data/doc/cxxapi/{classPassenger_1_1Thread-members.html → classPassenger_1_1FileChecker-members.html} +4 -5
  60. data/doc/cxxapi/classPassenger_1_1FileChecker.html +121 -0
  61. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -2
  62. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +2 -3
  63. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  64. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +2 -3
  65. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +2 -3
  66. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  67. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -2
  68. data/doc/cxxapi/classPassenger_1_1IOException.html +2 -3
  69. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +5 -2
  71. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +155 -5
  72. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption-members.html → classPassenger_1_1RuntimeException-members.html} +2 -3
  73. data/doc/cxxapi/{classboost_1_1this__thread_1_1enable__syscall__interruption.html → classPassenger_1_1RuntimeException.html} +10 -8
  74. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -2
  75. data/doc/cxxapi/classPassenger_1_1SpawnException.html +2 -3
  76. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +2 -3
  77. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +15 -56
  78. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +5 -4
  79. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +20 -81
  80. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  81. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +2 -3
  82. data/doc/cxxapi/classPassenger_1_1SystemException.html +9 -10
  83. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  84. data/doc/cxxapi/{classboost_1_1this__thread_1_1disable__syscall__interruption-members.html → classPassenger_1_1SystemTime-members.html} +5 -3
  85. data/doc/cxxapi/classPassenger_1_1SystemTime.html +86 -0
  86. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +2 -3
  87. data/doc/cxxapi/classPassenger_1_1TempFile.html +17 -9
  88. data/doc/cxxapi/definitions_8h-source.html +1 -2
  89. data/doc/cxxapi/files.html +6 -3
  90. data/doc/cxxapi/functions.html +98 -35
  91. data/doc/cxxapi/functions_func.html +60 -32
  92. data/doc/cxxapi/functions_type.html +1 -2
  93. data/doc/cxxapi/functions_vars.html +27 -2
  94. data/doc/cxxapi/graph_legend.html +1 -2
  95. data/doc/cxxapi/graph_legend.png +0 -0
  96. data/doc/cxxapi/group__Configuration.html +3 -4
  97. data/doc/cxxapi/group__Configuration.png +0 -0
  98. data/doc/cxxapi/group__Core.html +3 -4
  99. data/doc/cxxapi/group__Core.png +0 -0
  100. data/doc/cxxapi/group__Exceptions.html +4 -2
  101. data/doc/cxxapi/group__Hooks.html +1 -6
  102. data/doc/cxxapi/group__Hooks.png +0 -0
  103. data/doc/cxxapi/group__Support.html +259 -36
  104. data/doc/cxxapi/hierarchy.html +6 -7
  105. data/doc/cxxapi/inherit__graph__0.map +1 -1
  106. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  107. data/doc/cxxapi/inherit__graph__0.png +0 -0
  108. data/doc/cxxapi/inherit__graph__1.map +1 -1
  109. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  110. data/doc/cxxapi/inherit__graph__1.png +0 -0
  111. data/doc/cxxapi/inherit__graph__10.map +1 -1
  112. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  113. data/doc/cxxapi/inherit__graph__10.png +0 -0
  114. data/doc/cxxapi/inherit__graph__11.map +1 -1
  115. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  116. data/doc/cxxapi/inherit__graph__11.png +0 -0
  117. data/doc/cxxapi/inherit__graph__12.map +2 -1
  118. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  119. data/doc/cxxapi/inherit__graph__12.png +0 -0
  120. data/doc/cxxapi/inherit__graph__13.map +1 -1
  121. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__13.png +0 -0
  123. data/doc/cxxapi/inherit__graph__14.map +1 -2
  124. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__14.png +0 -0
  126. data/doc/cxxapi/inherit__graph__15.map +1 -1
  127. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__15.png +0 -0
  129. data/doc/cxxapi/inherit__graph__16.map +1 -1
  130. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__16.png +0 -0
  132. data/doc/cxxapi/inherit__graph__17.png +0 -0
  133. data/doc/cxxapi/inherit__graph__18.png +0 -0
  134. data/doc/cxxapi/inherit__graph__19.png +0 -0
  135. data/doc/cxxapi/inherit__graph__2.map +1 -1
  136. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__2.png +0 -0
  138. data/doc/cxxapi/inherit__graph__20.map +1 -1
  139. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__20.png +0 -0
  141. data/doc/cxxapi/inherit__graph__21.map +1 -1
  142. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__21.png +0 -0
  144. data/doc/cxxapi/inherit__graph__3.map +1 -1
  145. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__3.png +0 -0
  147. data/doc/cxxapi/inherit__graph__4.map +1 -1
  148. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__4.png +0 -0
  150. data/doc/cxxapi/inherit__graph__5.map +2 -1
  151. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__5.png +0 -0
  153. data/doc/cxxapi/inherit__graph__6.map +1 -1
  154. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__6.png +0 -0
  156. data/doc/cxxapi/inherit__graph__7.map +1 -1
  157. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__7.png +0 -0
  159. data/doc/cxxapi/inherit__graph__8.map +1 -1
  160. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__8.png +0 -0
  162. data/doc/cxxapi/inherit__graph__9.map +1 -2
  163. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__9.png +0 -0
  165. data/doc/cxxapi/inherits.html +30 -31
  166. data/doc/cxxapi/main.html +1 -2
  167. data/doc/cxxapi/modules.html +1 -2
  168. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -2
  169. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +2 -3
  170. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -2
  171. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +2 -3
  172. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +49 -0
  173. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +404 -0
  174. data/doc/cxxapi/tree.html +18 -20
  175. data/doc/images/conservative_spawning.png +0 -0
  176. data/doc/images/conservative_spawning.svg +248 -0
  177. data/doc/images/smart-lv2.png +0 -0
  178. data/doc/images/smart-lv2.svg +320 -0
  179. data/doc/rdoc/classes/ConditionVariable.html +68 -34
  180. data/doc/rdoc/classes/Exception.html +16 -16
  181. data/doc/rdoc/classes/GC.html +9 -9
  182. data/doc/rdoc/classes/IO.html +36 -17
  183. data/doc/rdoc/classes/PhusionPassenger.html +183 -0
  184. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +511 -0
  185. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer.html +285 -242
  186. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerAlreadyStarted.html +3 -3
  187. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerError.html +3 -3
  188. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/ServerNotStarted.html +3 -3
  189. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AbstractServer/UnknownMessage.html +3 -3
  190. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +598 -0
  191. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +140 -0
  192. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +247 -0
  193. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess/Instance.html +138 -0
  194. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/AppInitError.html +36 -19
  195. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/Application.html +81 -96
  196. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/ConsoleTextTemplate.html +18 -18
  197. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/FrameworkInitError.html +20 -18
  198. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/HTMLTemplate.html +18 -18
  199. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/InitializationError.html +9 -9
  200. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +92 -0
  201. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/MessageChannel.html +93 -92
  202. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/NativeSupport.html +55 -25
  203. data/doc/rdoc/classes/PhusionPassenger/Rack.html +91 -0
  204. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +185 -0
  205. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +182 -0
  206. data/doc/rdoc/classes/PhusionPassenger/Railz.html +95 -0
  207. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +424 -0
  208. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner/Error.html +98 -0
  209. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +200 -0
  210. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +444 -0
  211. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner/Error.html +98 -0
  212. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +154 -0
  213. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +408 -0
  214. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/UnknownError.html +13 -13
  215. data/doc/rdoc/classes/PhusionPassenger/Utils.html +687 -0
  216. data/doc/rdoc/classes/{Passenger → PhusionPassenger}/VersionNotFound.html +8 -8
  217. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +89 -0
  218. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +188 -0
  219. data/doc/rdoc/classes/PlatformInfo.html +663 -159
  220. data/doc/rdoc/classes/RakeExtensions.html +4 -4
  221. data/doc/rdoc/classes/Signal.html +134 -0
  222. data/doc/rdoc/created.rid +1 -1
  223. data/doc/rdoc/files/DEVELOPERS_TXT.html +15 -10
  224. data/doc/rdoc/files/README.html +5 -7
  225. data/doc/rdoc/files/ext/{passenger → phusion_passenger}/native_support_c.html +2 -2
  226. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_request_handler_rb.html +7 -9
  227. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +120 -0
  228. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/abstract_server_rb.html +7 -10
  229. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +99 -0
  230. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +92 -0
  231. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/application_rb.html +6 -8
  232. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/console_text_template_rb.html +5 -7
  233. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/constants_rb.html +4 -5
  234. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/dependencies_rb.html +6 -8
  235. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +116 -0
  236. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/exceptions_rb.html +5 -7
  237. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/html_template_rb.html +5 -7
  238. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/message_channel_rb.html +5 -7
  239. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/platform_info_rb.html +6 -7
  240. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +123 -0
  241. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +117 -0
  242. data/doc/rdoc/files/lib/{passenger/utils_rb.html → phusion_passenger/railz/application_spawner_rb.html} +24 -17
  243. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +126 -0
  244. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +139 -0
  245. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +118 -0
  246. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/simple_benchmarking_rb.html +5 -7
  247. data/doc/rdoc/files/lib/{passenger → phusion_passenger}/spawn_manager_rb.html +40 -24
  248. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +169 -0
  249. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +120 -0
  250. data/doc/rdoc/files/lib/rake/extensions_rb.html +3 -4
  251. data/doc/rdoc/fr_class_index.html +37 -19
  252. data/doc/rdoc/fr_file_index.html +25 -14
  253. data/doc/rdoc/fr_method_index.html +145 -74
  254. data/ext/apache2/Application.h +145 -44
  255. data/ext/apache2/ApplicationPool.h +27 -29
  256. data/ext/apache2/ApplicationPoolServer.h +183 -72
  257. data/ext/apache2/ApplicationPoolServerExecutable.cpp +249 -42
  258. data/ext/apache2/Bucket.cpp +61 -9
  259. data/ext/apache2/Bucket.h +15 -8
  260. data/ext/apache2/CachedFileStat.cpp +114 -0
  261. data/ext/apache2/CachedFileStat.h +169 -0
  262. data/ext/apache2/Configuration.cpp +213 -22
  263. data/ext/apache2/Configuration.h +176 -13
  264. data/ext/apache2/DirectoryMapper.h +287 -0
  265. data/ext/apache2/Exceptions.h +30 -12
  266. data/ext/apache2/FileChecker.h +108 -0
  267. data/ext/apache2/Hooks.cpp +709 -493
  268. data/ext/apache2/LICENSE-CNRI.TXT +15 -0
  269. data/ext/apache2/Logging.h +26 -22
  270. data/ext/apache2/MessageChannel.h +124 -15
  271. data/ext/apache2/PoolOptions.h +283 -0
  272. data/ext/apache2/SpawnManager.h +75 -99
  273. data/ext/apache2/StandardApplicationPool.h +296 -195
  274. data/ext/apache2/SystemTime.cpp +28 -0
  275. data/ext/apache2/SystemTime.h +82 -0
  276. data/ext/apache2/Utils.cpp +172 -18
  277. data/ext/apache2/Utils.h +124 -19
  278. data/ext/boost/cstdint.hpp +4 -2
  279. data/ext/boost/current_function.hpp +67 -0
  280. data/ext/boost/detail/sp_counted_base.hpp +4 -4
  281. data/ext/boost/thread/exceptions.hpp +2 -1
  282. data/ext/boost/thread/pthread/thread.hpp +11 -3
  283. data/ext/boost/thread/pthread/thread_data.hpp +2 -1
  284. data/ext/oxt/backtrace.cpp +172 -0
  285. data/ext/oxt/backtrace.hpp +135 -0
  286. data/ext/oxt/detail/backtrace_disabled.hpp +39 -0
  287. data/ext/oxt/detail/backtrace_enabled.hpp +155 -0
  288. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +82 -0
  289. data/ext/oxt/detail/spin_lock_portable.hpp +38 -0
  290. data/ext/oxt/detail/spin_lock_pthreads.hpp +97 -0
  291. data/ext/oxt/detail/tracable_exception_disabled.hpp +46 -0
  292. data/ext/oxt/detail/tracable_exception_enabled.hpp +48 -0
  293. data/ext/oxt/macros.hpp +58 -0
  294. data/ext/oxt/spin_lock.hpp +55 -0
  295. data/ext/{apache2/System.cpp → oxt/system_calls.cpp} +87 -52
  296. data/ext/oxt/system_calls.hpp +234 -0
  297. data/ext/oxt/thread.cpp +32 -0
  298. data/ext/oxt/thread.hpp +223 -0
  299. data/ext/oxt/tracable_exception.cpp +87 -0
  300. data/ext/oxt/tracable_exception.hpp +35 -0
  301. data/{lib/passenger/constants.rb → ext/phusion_passenger/extconf.rb} +14 -9
  302. data/ext/{passenger → phusion_passenger}/native_support.c +33 -6
  303. data/lib/{passenger → phusion_passenger}/abstract_request_handler.rb +209 -93
  304. data/lib/{passenger → phusion_passenger}/abstract_server.rb +23 -8
  305. data/lib/phusion_passenger/abstract_server_collection.rb +301 -0
  306. data/lib/phusion_passenger/admin_tools.rb +25 -0
  307. data/lib/phusion_passenger/admin_tools/control_process.rb +107 -0
  308. data/lib/{passenger → phusion_passenger}/application.rb +13 -16
  309. data/lib/{passenger → phusion_passenger}/console_text_template.rb +2 -2
  310. data/{ext/passenger/extconf.rb → lib/phusion_passenger/constants.rb} +5 -5
  311. data/lib/{passenger → phusion_passenger}/dependencies.rb +38 -32
  312. data/lib/phusion_passenger/events.rb +45 -0
  313. data/lib/{passenger → phusion_passenger}/exceptions.rb +12 -5
  314. data/lib/{passenger → phusion_passenger}/html_template.rb +2 -2
  315. data/lib/{passenger → phusion_passenger}/message_channel.rb +3 -2
  316. data/lib/phusion_passenger/platform_info.rb +500 -0
  317. data/lib/{passenger → phusion_passenger}/rack/application_spawner.rb +29 -22
  318. data/lib/{passenger → phusion_passenger}/rack/request_handler.rb +14 -9
  319. data/lib/{passenger → phusion_passenger}/railz/application_spawner.rb +94 -74
  320. data/lib/{passenger → phusion_passenger}/railz/cgi_fixed.rb +2 -2
  321. data/lib/{passenger → phusion_passenger}/railz/framework_spawner.rb +86 -98
  322. data/lib/{passenger → phusion_passenger}/railz/request_handler.rb +6 -6
  323. data/lib/{passenger → phusion_passenger}/simple_benchmarking.rb +0 -0
  324. data/lib/{passenger → phusion_passenger}/spawn_manager.rb +136 -128
  325. data/lib/{passenger → phusion_passenger}/templates/apache2_config_snippets.txt.erb +0 -0
  326. data/lib/{passenger → phusion_passenger}/templates/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  327. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +38 -0
  328. data/lib/{passenger → phusion_passenger}/templates/app_init_error.html.erb +0 -0
  329. data/lib/{passenger → phusion_passenger}/templates/database_error.html.erb +0 -0
  330. data/lib/{passenger → phusion_passenger}/templates/deployment_example.txt.erb +1 -1
  331. data/lib/{passenger → phusion_passenger}/templates/error_layout.css +0 -0
  332. data/lib/{passenger → phusion_passenger}/templates/error_layout.html.erb +0 -0
  333. data/lib/{passenger → phusion_passenger}/templates/framework_init_error.html.erb +0 -0
  334. data/lib/{passenger → phusion_passenger}/templates/general_error.html.erb +0 -0
  335. data/lib/{passenger → phusion_passenger}/templates/invalid_app_root.html.erb +1 -1
  336. data/lib/{passenger → phusion_passenger}/templates/load_error.html.erb +0 -0
  337. data/lib/{passenger → phusion_passenger}/templates/no_write_permission_to_passenger_root.txt.erb +0 -0
  338. data/lib/{passenger → phusion_passenger}/templates/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  339. data/lib/{passenger → phusion_passenger}/templates/run_installer_as_root.txt.erb +0 -0
  340. data/lib/{passenger → phusion_passenger}/templates/version_not_found.html.erb +0 -0
  341. data/lib/{passenger → phusion_passenger}/templates/welcome.txt.erb +0 -0
  342. data/lib/{passenger → phusion_passenger}/utils.rb +210 -44
  343. data/lib/{passenger → phusion_passenger}/wsgi/application_spawner.rb +18 -15
  344. data/lib/{passenger → phusion_passenger}/wsgi/request_handler.py +7 -1
  345. data/man/passenger-memory-stats.8 +1 -1
  346. data/misc/render_error_pages.rb +1 -1
  347. data/test/ApplicationPoolServerTest.cpp +0 -28
  348. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +4 -0
  349. data/test/ApplicationPoolTest.cpp +307 -69
  350. data/test/CachedFileStatTest.cpp +262 -0
  351. data/test/FileCheckerTest.cpp +79 -0
  352. data/test/MessageChannelTest.cpp +3 -3
  353. data/test/PoolOptionsTest.cpp +37 -0
  354. data/test/SpawnManagerTest.cpp +4 -4
  355. data/test/StandardApplicationPoolTest.cpp +4 -0
  356. data/test/SystemTimeTest.cpp +37 -0
  357. data/test/UtilsTest.cpp +137 -0
  358. data/test/integration_tests.rb +270 -23
  359. data/test/oxt/backtrace_test.cpp +128 -0
  360. data/test/oxt/oxt_test_main.cpp +25 -0
  361. data/test/oxt/syscall_interruption_test.cpp +50 -0
  362. data/test/ruby/abstract_request_handler_spec.rb +83 -0
  363. data/test/ruby/abstract_server_collection_spec.rb +246 -0
  364. data/test/ruby/application_spec.rb +3 -3
  365. data/test/ruby/message_channel_spec.rb +2 -2
  366. data/test/ruby/rack/application_spawner_spec.rb +3 -5
  367. data/test/ruby/rails/application_spawner_spec.rb +54 -15
  368. data/test/ruby/rails/framework_spawner_spec.rb +6 -8
  369. data/test/ruby/rails/minimal_spawner_spec.rb +29 -0
  370. data/test/ruby/rails/spawner_error_handling_spec.rb +1 -1
  371. data/test/ruby/rails/spawner_privilege_lowering_spec.rb +3 -3
  372. data/test/ruby/spawn_manager_spec.rb +23 -12
  373. data/test/ruby/utils_spec.rb +36 -2
  374. data/test/ruby/wsgi/application_spawner_spec.rb +47 -0
  375. data/test/stub/apache2/httpd.conf.erb +3 -5
  376. data/test/stub/message_channel.rb +2 -2
  377. data/test/stub/message_channel_2.rb +2 -2
  378. data/test/stub/message_channel_3.rb +3 -3
  379. data/test/stub/minimal-railsapp/README +0 -0
  380. data/test/stub/minimal-railsapp/config/application.rb +0 -0
  381. data/test/stub/minimal-railsapp/config/environment.rb +0 -0
  382. data/test/stub/minimal-railsapp/vendor/rails/actionmailer/lib/action_mailer.rb +0 -0
  383. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_controller.rb +0 -0
  384. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_pack.rb +0 -0
  385. data/test/stub/minimal-railsapp/vendor/rails/actionpack/lib/action_view.rb +0 -0
  386. data/test/stub/minimal-railsapp/vendor/rails/activerecord/lib/active_record.rb +0 -0
  387. data/test/stub/minimal-railsapp/vendor/rails/activeresource/lib/active_resource.rb +0 -0
  388. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support.rb +0 -0
  389. data/test/stub/minimal-railsapp/vendor/rails/activesupport/lib/active_support/whiny_nil.rb +0 -0
  390. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/dispatcher.rb +0 -0
  391. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/initializer.rb +0 -0
  392. data/test/stub/minimal-railsapp/vendor/rails/railties/lib/ruby_version_check.rb +0 -0
  393. data/test/stub/rails_apps/foobar/app/controllers/foo_controller.rb +8 -0
  394. data/test/stub/rails_apps/foobar/config/environments/development.rb +1 -2
  395. data/test/stub/rails_apps/mycook/app/controllers/welcome_controller.rb +21 -1
  396. data/test/stub/rails_apps/mycook/sites/some.site/public/uploads.html +26 -0
  397. data/test/stub/rails_apps/mycook/sites/some.site/public/welcome/cached.html +26 -0
  398. data/test/stub/railsapp/app/controllers/application.rb +0 -0
  399. data/test/stub/railsapp/app/controllers/bar_controller_1.rb +0 -0
  400. data/test/stub/railsapp/app/controllers/bar_controller_2.rb +1 -1
  401. data/test/stub/railsapp/app/controllers/foo_controller.rb +4 -0
  402. data/test/stub/railsapp/app/helpers/application_helper.rb +0 -0
  403. data/test/stub/railsapp/config/boot.rb +0 -0
  404. data/test/stub/railsapp/config/database.yml +0 -0
  405. data/test/stub/railsapp/config/environment.rb +0 -0
  406. data/test/stub/railsapp/config/environments/development.rb +0 -0
  407. data/test/stub/railsapp/config/environments/production.rb +0 -0
  408. data/test/stub/railsapp/config/initializers/inflections.rb +0 -0
  409. data/test/stub/railsapp/config/initializers/mime_types.rb +0 -0
  410. data/test/stub/railsapp/config/routes.rb +0 -0
  411. data/test/stub/railsapp/public/useless.txt +0 -0
  412. data/test/stub/spawn_server.rb +3 -4
  413. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  414. data/test/support/apache2_controller.rb +57 -7
  415. data/test/support/tut.h +15 -0
  416. data/vendor/README +12 -0
  417. data/vendor/README_FOR_PACKAGERS +1 -0
  418. data/vendor/rack-0.9.1/AUTHORS +8 -0
  419. data/vendor/rack-0.9.1/COPYING +18 -0
  420. data/vendor/rack-0.9.1/ChangeLog +1423 -0
  421. data/vendor/rack-0.9.1/KNOWN-ISSUES +18 -0
  422. data/vendor/rack-0.9.1/README +306 -0
  423. data/vendor/rack-0.9.1/Rakefile +188 -0
  424. data/vendor/rack-0.9.1/SPEC +129 -0
  425. data/vendor/rack-0.9.1/lib/rack.rb +86 -0
  426. data/vendor/rack-0.9.1/lib/rack/adapter/camping.rb +22 -0
  427. data/vendor/rack-0.9.1/lib/rack/auth/abstract/handler.rb +28 -0
  428. data/vendor/rack-0.9.1/lib/rack/auth/abstract/request.rb +37 -0
  429. data/vendor/rack-0.9.1/lib/rack/auth/basic.rb +58 -0
  430. data/vendor/rack-0.9.1/lib/rack/auth/digest/md5.rb +124 -0
  431. data/vendor/rack-0.9.1/lib/rack/auth/digest/nonce.rb +51 -0
  432. data/vendor/rack-0.9.1/lib/rack/auth/digest/params.rb +55 -0
  433. data/vendor/rack-0.9.1/lib/rack/auth/digest/request.rb +40 -0
  434. data/vendor/rack-0.9.1/lib/rack/auth/openid.rb +438 -0
  435. data/vendor/rack-0.9.1/lib/rack/builder.rb +67 -0
  436. data/vendor/rack-0.9.1/lib/rack/cascade.rb +36 -0
  437. data/vendor/rack-0.9.1/lib/rack/commonlogger.rb +61 -0
  438. data/vendor/rack-0.9.1/lib/rack/conditionalget.rb +43 -0
  439. data/vendor/rack-0.9.1/lib/rack/content_length.rb +25 -0
  440. data/vendor/rack-0.9.1/lib/rack/deflater.rb +87 -0
  441. data/vendor/rack-0.9.1/lib/rack/directory.rb +150 -0
  442. data/vendor/rack-0.9.1/lib/rack/file.rb +85 -0
  443. data/vendor/rack-0.9.1/lib/rack/handler.rb +48 -0
  444. data/vendor/rack-0.9.1/lib/rack/handler/cgi.rb +57 -0
  445. data/vendor/rack-0.9.1/lib/rack/handler/evented_mongrel.rb +8 -0
  446. data/vendor/rack-0.9.1/lib/rack/handler/fastcgi.rb +86 -0
  447. data/vendor/rack-0.9.1/lib/rack/handler/lsws.rb +52 -0
  448. data/vendor/rack-0.9.1/lib/rack/handler/mongrel.rb +82 -0
  449. data/vendor/rack-0.9.1/lib/rack/handler/scgi.rb +57 -0
  450. data/vendor/rack-0.9.1/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  451. data/vendor/rack-0.9.1/lib/rack/handler/thin.rb +15 -0
  452. data/vendor/rack-0.9.1/lib/rack/handler/webrick.rb +61 -0
  453. data/vendor/rack-0.9.1/lib/rack/head.rb +19 -0
  454. data/vendor/rack-0.9.1/lib/rack/lint.rb +465 -0
  455. data/vendor/rack-0.9.1/lib/rack/lobster.rb +65 -0
  456. data/vendor/rack-0.9.1/lib/rack/methodoverride.rb +27 -0
  457. data/vendor/rack-0.9.1/lib/rack/mime.rb +204 -0
  458. data/vendor/rack-0.9.1/lib/rack/mock.rb +160 -0
  459. data/vendor/rack-0.9.1/lib/rack/recursive.rb +57 -0
  460. data/vendor/rack-0.9.1/lib/rack/reloader.rb +64 -0
  461. data/vendor/rack-0.9.1/lib/rack/request.rb +218 -0
  462. data/vendor/rack-0.9.1/lib/rack/response.rb +171 -0
  463. data/vendor/rack-0.9.1/lib/rack/session/abstract/id.rb +153 -0
  464. data/vendor/rack-0.9.1/lib/rack/session/cookie.rb +89 -0
  465. data/vendor/rack-0.9.1/lib/rack/session/memcache.rb +97 -0
  466. data/vendor/rack-0.9.1/lib/rack/session/pool.rb +73 -0
  467. data/vendor/rack-0.9.1/lib/rack/showexceptions.rb +348 -0
  468. data/vendor/rack-0.9.1/lib/rack/showstatus.rb +106 -0
  469. data/vendor/rack-0.9.1/lib/rack/static.rb +38 -0
  470. data/vendor/rack-0.9.1/lib/rack/urlmap.rb +48 -0
  471. data/vendor/rack-0.9.1/lib/rack/utils.rb +347 -0
  472. metadata +1197 -1055
  473. data/doc/cxxapi/System_8h-source.html +0 -251
  474. data/doc/cxxapi/classDirectoryMapper-members.html +0 -38
  475. data/doc/cxxapi/classDirectoryMapper.html +0 -203
  476. data/doc/cxxapi/classPassenger_1_1Thread.html +0 -100
  477. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +0 -46
  478. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +0 -33
  479. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +0 -44
  480. data/doc/cxxapi/namespacePassenger.html +0 -208
  481. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +0 -43
  482. data/doc/cxxapi/namespacemembers.html +0 -70
  483. data/doc/cxxapi/namespacemembers_func.html +0 -66
  484. data/doc/cxxapi/namespacemembers_type.html +0 -46
  485. data/doc/cxxapi/namespaces.html +0 -35
  486. data/doc/rdoc/classes/Passenger.html +0 -136
  487. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +0 -402
  488. data/doc/rdoc/classes/Passenger/SpawnManager.html +0 -379
  489. data/doc/rdoc/classes/Passenger/Utils.html +0 -578
  490. data/ext/apache2/System.h +0 -228
  491. data/lib/passenger/platform_info.rb +0 -302
  492. data/lib/passenger/templates/app_exited_during_initialization.html.erb +0 -19
  493. data/test/stub/apache2/httpd.conf +0 -75
  494. data/test/stub/rails_apps/foobar/config/environments/test.rb +0 -22
  495. data/test/stub/rails_apps/mycook/config/environments/test.rb +0 -22
  496. data/test/stub/railsapp/config/environments/test.rb +0 -22
  497. data/test/stub/railsapp2/config/environments/test.rb +0 -22
@@ -10,7 +10,6 @@
10
10
  <ul>
11
11
  <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
12
12
  <li><a href="modules.html"><span>Modules</span></a></li>
13
- <li><a href="namespaces.html"><span>Namespaces</span></a></li>
14
13
  <li><a href="annotated.html"><span>Classes</span></a></li>
15
14
  <li class="current"><a href="files.html"><span>Files</span></a></li>
16
15
  </ul>
@@ -44,687 +43,788 @@
44
43
  <a name="l00027"></a>00027 <span class="preprocessor">#include &lt;boost/date_time/microsec_time_clock.hpp&gt;</span>
45
44
  <a name="l00028"></a>00028 <span class="preprocessor">#include &lt;boost/date_time/posix_time/posix_time.hpp&gt;</span>
46
45
  <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>
46
+ <a name="l00030"></a>00030 <span class="preprocessor">#include &lt;oxt/system_calls.hpp&gt;</span>
47
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;oxt/backtrace.hpp&gt;</span>
48
+ <a name="l00032"></a>00032
49
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &lt;string&gt;</span>
50
+ <a name="l00034"></a>00034 <span class="preprocessor">#include &lt;sstream&gt;</span>
51
+ <a name="l00035"></a>00035 <span class="preprocessor">#include &lt;map&gt;</span>
52
+ <a name="l00036"></a>00036 <span class="preprocessor">#include &lt;list&gt;</span>
53
+ <a name="l00037"></a>00037
54
+ <a name="l00038"></a>00038 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
55
+ <a name="l00039"></a>00039 <span class="preprocessor">#include &lt;sys/stat.h&gt;</span>
56
+ <a name="l00040"></a>00040 <span class="preprocessor">#include &lt;stdio.h&gt;</span>
57
+ <a name="l00041"></a>00041 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
58
+ <a name="l00042"></a>00042 <span class="preprocessor">#include &lt;ctime&gt;</span>
59
+ <a name="l00043"></a>00043 <span class="preprocessor">#include &lt;cerrno&gt;</span>
60
+ <a name="l00044"></a>00044 <span class="preprocessor">#ifdef TESTING_APPLICATION_POOL</span>
61
+ <a name="l00045"></a>00045 <span class="preprocessor"></span><span class="preprocessor"> #include &lt;cstdlib&gt;</span>
62
+ <a name="l00046"></a>00046 <span class="preprocessor">#endif</span>
63
+ <a name="l00047"></a>00047 <span class="preprocessor"></span>
64
+ <a name="l00048"></a>00048 <span class="preprocessor">#include "ApplicationPool.h"</span>
65
+ <a name="l00049"></a>00049 <span class="preprocessor">#include "Logging.h"</span>
66
+ <a name="l00050"></a>00050 <span class="preprocessor">#include "FileChecker.h"</span>
67
+ <a name="l00051"></a>00051 <span class="preprocessor">#include "CachedFileStat.h"</span>
68
+ <a name="l00052"></a>00052 <span class="preprocessor">#ifdef PASSENGER_USE_DUMMY_SPAWN_MANAGER</span>
69
+ <a name="l00053"></a>00053 <span class="preprocessor"></span><span class="preprocessor"> #include "DummySpawnManager.h"</span>
70
+ <a name="l00054"></a>00054 <span class="preprocessor">#else</span>
71
+ <a name="l00055"></a>00055 <span class="preprocessor"></span><span class="preprocessor"> #include "SpawnManager.h"</span>
72
+ <a name="l00056"></a>00056 <span class="preprocessor">#endif</span>
73
+ <a name="l00057"></a>00057 <span class="preprocessor"></span>
74
+ <a name="l00058"></a>00058 <span class="keyword">namespace </span>Passenger {
75
+ <a name="l00059"></a>00059
76
+ <a name="l00060"></a>00060 <span class="keyword">using namespace </span>std;
77
+ <a name="l00061"></a>00061 <span class="keyword">using namespace </span>boost;
78
+ <a name="l00062"></a>00062 <span class="keyword">using namespace </span>oxt;
79
+ <a name="l00063"></a>00063
80
+ <a name="l00064"></a>00064 <span class="keyword">class </span>ApplicationPoolServer;
81
+ <a name="l00065"></a>00065
82
+ <a name="l00066"></a>00066 <span class="comment">/****************************************************************</span>
83
+ <a name="l00067"></a>00067 <span class="comment"> *</span>
84
+ <a name="l00068"></a>00068 <span class="comment"> * See "doc/ApplicationPool algorithm.txt" for a more readable</span>
85
+ <a name="l00069"></a>00069 <span class="comment"> * and detailed description of the algorithm implemented here.</span>
87
86
  <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>
87
+ <a name="l00071"></a>00071 <span class="comment"> ****************************************************************/</span>
88
+ <a name="l00072"></a>00072 <span class="comment"></span>
89
+ <a name="l00073"></a>00073 <span class="comment">/**</span>
90
+ <a name="l00074"></a>00074 <span class="comment"> * A standard implementation of ApplicationPool for single-process environments.</span>
91
+ <a name="l00075"></a>00075 <span class="comment"> *</span>
92
+ <a name="l00076"></a>00076 <span class="comment"> * The environment may or may not be multithreaded - StandardApplicationPool is completely</span>
93
+ <a name="l00077"></a>00077 <span class="comment"> * thread-safe. Apache with the threading MPM is an example of a multithreaded single-process</span>
94
+ <a name="l00078"></a>00078 <span class="comment"> * environment.</span>
95
+ <a name="l00079"></a>00079 <span class="comment"> *</span>
96
+ <a name="l00080"></a>00080 <span class="comment"> * This class is unusable in multi-process environments such as Apache with the prefork MPM.</span>
97
+ <a name="l00081"></a>00081 <span class="comment"> * The reasons are as follows:</span>
98
+ <a name="l00082"></a>00082 <span class="comment"> * - StandardApplicationPool uses threads internally. Because threads disappear after a fork(),</span>
99
+ <a name="l00083"></a>00083 <span class="comment"> * a StandardApplicationPool object will become unusable after a fork().</span>
100
+ <a name="l00084"></a>00084 <span class="comment"> * - StandardApplicationPool stores its internal cache on the heap. Different processes</span>
101
+ <a name="l00085"></a>00085 <span class="comment"> * cannot share their heaps, so they will not be able to access each others' pool cache.</span>
102
+ <a name="l00086"></a>00086 <span class="comment"> * - StandardApplicationPool has a connection to the spawn server. If there are multiple</span>
103
+ <a name="l00087"></a>00087 <span class="comment"> * processes, and they all use the spawn servers's connection at the same time without</span>
104
+ <a name="l00088"></a>00088 <span class="comment"> * some sort of synchronization, then bad things will happen.</span>
106
105
  <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">if</span> (active &gt;= max) {
470
- <a name="l00453"></a>00453 activeOrMaxChanged.wait(l);
471
- <a name="l00454"></a>00454 <span class="keywordflow">goto</span> beginning_of_function;
472
- <a name="l00455"></a>00455 }
473
- <a name="l00456"></a>00456 <span class="keywordflow">if</span> (count == max) {
474
- <a name="l00457"></a>00457 container = inactiveApps.front();
475
- <a name="l00458"></a>00458 inactiveApps.pop_front();
476
- <a name="l00459"></a>00459 list = apps[container-&gt;app-&gt;getAppRoot()].get();
477
- <a name="l00460"></a>00460 list-&gt;erase(container-&gt;iterator);
478
- <a name="l00461"></a>00461 <span class="keywordflow">if</span> (list-&gt;empty()) {
479
- <a name="l00462"></a>00462 apps.erase(container-&gt;app-&gt;getAppRoot());
480
- <a name="l00463"></a>00463 restartFileTimes.erase(container-&gt;app-&gt;getAppRoot());
481
- <a name="l00464"></a>00464 appInstanceCount.erase(container-&gt;app-&gt;getAppRoot());
482
- <a name="l00465"></a>00465 } <span class="keywordflow">else</span> {
483
- <a name="l00466"></a>00466 appInstanceCount[container-&gt;app-&gt;getAppRoot()]--;
484
- <a name="l00467"></a>00467 }
485
- <a name="l00468"></a>00468 count--;
486
- <a name="l00469"></a>00469 }
487
- <a name="l00470"></a>00470 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());
488
- <a name="l00471"></a>00471 {
489
- <a name="l00472"></a>00472 this_thread::restore_interruption ri(di);
490
- <a name="l00473"></a>00473 <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);
491
- <a name="l00474"></a>00474 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,
492
- <a name="l00475"></a>00475 environment, spawnMethod, appType);
493
- <a name="l00476"></a>00476 }
494
- <a name="l00477"></a>00477 container-&gt;sessions = 0;
495
- <a name="l00478"></a>00478 it = apps.find(appRoot);
496
- <a name="l00479"></a>00479 <span class="keywordflow">if</span> (it == apps.end()) {
497
- <a name="l00480"></a>00480 list = <span class="keyword">new</span> AppContainerList();
498
- <a name="l00481"></a>00481 apps[appRoot] = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(list);
499
- <a name="l00482"></a>00482 appInstanceCount[appRoot] = 1;
500
- <a name="l00483"></a>00483 } <span class="keywordflow">else</span> {
501
- <a name="l00484"></a>00484 list = it-&gt;second.get();
502
- <a name="l00485"></a>00485 appInstanceCount[appRoot]++;
503
- <a name="l00486"></a>00486 }
504
- <a name="l00487"></a>00487 list-&gt;push_back(container);
505
- <a name="l00488"></a>00488 container-&gt;iterator = list-&gt;end();
506
- <a name="l00489"></a>00489 container-&gt;iterator--;
507
- <a name="l00490"></a>00490 count++;
508
- <a name="l00491"></a>00491 active++;
509
- <a name="l00492"></a>00492 activeOrMaxChanged.notify_all();
510
- <a name="l00493"></a>00493 }
511
- <a name="l00494"></a>00494 } <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) {
512
- <a name="l00495"></a>00495 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
513
- <a name="l00496"></a>00496 message.append(appRoot);
514
- <a name="l00497"></a>00497 message.append(<span class="stringliteral">"': "</span>);
515
- <a name="l00498"></a>00498 message.append(e.<a class="code" href="classPassenger_1_1SpawnException.html#d2da180f89a43423a4b37248249972ff">what</a>());
516
- <a name="l00499"></a>00499 <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>()) {
517
- <a name="l00500"></a>00500 <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>());
518
- <a name="l00501"></a>00501 } <span class="keywordflow">else</span> {
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);
520
- <a name="l00503"></a>00503 }
521
- <a name="l00504"></a>00504 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
522
- <a name="l00505"></a>00505 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
523
- <a name="l00506"></a>00506 message.append(appRoot);
524
- <a name="l00507"></a>00507 message.append(<span class="stringliteral">"': "</span>);
525
- <a name="l00508"></a>00508 message.append(e.what());
526
- <a name="l00509"></a>00509 <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);
527
- <a name="l00510"></a>00510 }
528
- <a name="l00511"></a>00511
529
- <a name="l00512"></a>00512 <span class="keywordflow">return</span> make_pair(container, list);
530
- <a name="l00513"></a>00513 }
531
- <a name="l00514"></a>00514
532
- <a name="l00515"></a>00515 <span class="keyword">public</span>:<span class="comment"></span>
533
- <a name="l00516"></a>00516 <span class="comment"> /**</span>
534
- <a name="l00517"></a>00517 <span class="comment"> * Create a new StandardApplicationPool object.</span>
535
- <a name="l00518"></a>00518 <span class="comment"> *</span>
536
- <a name="l00519"></a>00519 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
537
- <a name="l00520"></a>00520 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
538
- <a name="l00521"></a>00521 <span class="comment"> * Messages on its standard output and standard error channels</span>
539
- <a name="l00522"></a>00522 <span class="comment"> * will be written to this log file. If an empty string is</span>
540
- <a name="l00523"></a>00523 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
541
- <a name="l00524"></a>00524 <span class="comment"> * will use the same standard output/error channels as the</span>
542
- <a name="l00525"></a>00525 <span class="comment"> * current process.</span>
543
- <a name="l00526"></a>00526 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
544
- <a name="l00527"></a>00527 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
545
- <a name="l00528"></a>00528 <span class="comment"> * parameter only has effect if the current process is</span>
546
- <a name="l00529"></a>00529 <span class="comment"> * running as root. If the empty string is given, or if</span>
547
- <a name="l00530"></a>00530 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
548
- <a name="l00531"></a>00531 <span class="comment"> * the spawn manager will be run as the current user.</span>
549
- <a name="l00532"></a>00532 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
550
- <a name="l00533"></a>00533 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server.</span>
551
- <a name="l00534"></a>00534 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
552
- <a name="l00535"></a>00535 <span class="comment"> */</span>
553
- <a name="l00536"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#f175704fc477f37ba1d387be09fa2e6b">00536</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,
554
- <a name="l00537"></a>00537 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
555
- <a name="l00538"></a>00538 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
556
- <a name="l00539"></a>00539 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
557
- <a name="l00540"></a>00540 :
558
- <a name="l00541"></a>00541 #ifndef PASSENGER_USE_DUMMY_SPAWN_MANAGER
559
- <a name="l00542"></a>00542 spawnManager(spawnServerCommand, logFile, rubyCommand, user),
560
- <a name="l00543"></a>00543 #endif
561
- <a name="l00544"></a>00544 data(new SharedData()),
562
- <a name="l00545"></a>00545 lock(data-&gt;lock),
563
- <a name="l00546"></a>00546 activeOrMaxChanged(data-&gt;activeOrMaxChanged),
564
- <a name="l00547"></a>00547 apps(data-&gt;apps),
565
- <a name="l00548"></a>00548 max(data-&gt;max),
566
- <a name="l00549"></a>00549 count(data-&gt;count),
567
- <a name="l00550"></a>00550 active(data-&gt;active),
568
- <a name="l00551"></a>00551 maxPerApp(data-&gt;maxPerApp),
569
- <a name="l00552"></a>00552 inactiveApps(data-&gt;inactiveApps),
570
- <a name="l00553"></a>00553 restartFileTimes(data-&gt;restartFileTimes),
571
- <a name="l00554"></a>00554 appInstanceCount(data-&gt;appInstanceCount)
572
- <a name="l00555"></a>00555 {
573
- <a name="l00556"></a>00556 detached = <span class="keyword">false</span>;
574
- <a name="l00557"></a>00557 done = <span class="keyword">false</span>;
575
- <a name="l00558"></a>00558 max = DEFAULT_MAX_POOL_SIZE;
576
- <a name="l00559"></a>00559 count = 0;
577
- <a name="l00560"></a>00560 active = 0;
578
- <a name="l00561"></a>00561 useGlobalQueue = <span class="keyword">false</span>;
579
- <a name="l00562"></a>00562 waitingOnGlobalQueue = 0;
580
- <a name="l00563"></a>00563 maxPerApp = DEFAULT_MAX_INSTANCES_PER_APP;
581
- <a name="l00564"></a>00564 maxIdleTime = DEFAULT_MAX_IDLE_TIME;
582
- <a name="l00565"></a>00565 cleanerThread = <span class="keyword">new</span> thread(
583
- <a name="l00566"></a>00566 bind(&amp;StandardApplicationPool::cleanerThreadMainLoop, <span class="keyword">this</span>),
584
- <a name="l00567"></a>00567 CLEANER_THREAD_STACK_SIZE
585
- <a name="l00568"></a>00568 );
586
- <a name="l00569"></a>00569 }
587
- <a name="l00570"></a>00570
588
- <a name="l00571"></a>00571 <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>() {
589
- <a name="l00572"></a>00572 <span class="keywordflow">if</span> (!detached) {
590
- <a name="l00573"></a>00573 this_thread::disable_interruption di;
591
- <a name="l00574"></a>00574 {
592
- <a name="l00575"></a>00575 mutex::scoped_lock l(lock);
593
- <a name="l00576"></a>00576 done = <span class="keyword">true</span>;
594
- <a name="l00577"></a>00577 cleanerThreadSleeper.notify_one();
595
- <a name="l00578"></a>00578 }
596
- <a name="l00579"></a>00579 cleanerThread-&gt;join();
597
- <a name="l00580"></a>00580 }
598
- <a name="l00581"></a>00581 <span class="keyword">delete</span> cleanerThread;
599
- <a name="l00582"></a>00582 }
600
- <a name="l00583"></a>00583
601
- <a name="l00584"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#0dcdd88c39d7f1a1d667e24c3cb9b243">00584</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>(
602
- <a name="l00585"></a>00585 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot,
603
- <a name="l00586"></a>00586 <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
604
- <a name="l00587"></a>00587 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>,
605
- <a name="l00588"></a>00588 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
606
- <a name="l00589"></a>00589 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnMethod = <span class="stringliteral">"smart"</span>,
607
- <a name="l00590"></a>00590 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appType = <span class="stringliteral">"rails"</span>
608
- <a name="l00591"></a>00591 ) {
609
- <a name="l00592"></a>00592 <span class="keyword">using namespace </span>boost::posix_time;
610
- <a name="l00593"></a>00593 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> attempt = 0;
611
- <a name="l00594"></a>00594 ptime timeLimit(get_system_time() + millisec(GET_TIMEOUT));
612
- <a name="l00595"></a>00595 unique_lock&lt;mutex&gt; l(lock);
613
- <a name="l00596"></a>00596
614
- <a name="l00597"></a>00597 <span class="keywordflow">while</span> (<span class="keyword">true</span>) {
615
- <a name="l00598"></a>00598 attempt++;
616
- <a name="l00599"></a>00599
617
- <a name="l00600"></a>00600 pair&lt;AppContainerPtr, AppContainerList *&gt; p(
618
- <a name="l00601"></a>00601 spawnOrUseExisting(l, appRoot, lowerPrivilege, lowestUser,
619
- <a name="l00602"></a>00602 environment, spawnMethod, appType)
620
- <a name="l00603"></a>00603 );
621
- <a name="l00604"></a>00604 AppContainerPtr &amp;container(p.first);
622
- <a name="l00605"></a>00605 AppContainerList &amp;list(*p.second);
623
- <a name="l00606"></a>00606
624
- <a name="l00607"></a>00607 container-&gt;lastUsed = time(NULL);
625
- <a name="l00608"></a>00608 container-&gt;sessions++;
626
- <a name="l00609"></a>00609
627
- <a name="l00610"></a>00610 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
628
- <a name="l00611"></a>00611 <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>));
629
- <a name="l00612"></a>00612 <span class="keywordflow">try</span> {
630
- <a name="l00613"></a>00613 <span class="keywordflow">return</span> container-&gt;app-&gt;connect(SessionCloseCallback(data, container));
631
- <a name="l00614"></a>00614 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
632
- <a name="l00615"></a>00615 container-&gt;sessions--;
633
- <a name="l00616"></a>00616 <span class="keywordflow">if</span> (attempt == MAX_GET_ATTEMPTS) {
634
- <a name="l00617"></a>00617 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot connect to an existing "</span>
635
- <a name="l00618"></a>00618 <span class="stringliteral">"application instance for '"</span>);
636
- <a name="l00619"></a>00619 message.append(appRoot);
637
- <a name="l00620"></a>00620 message.append(<span class="stringliteral">"': "</span>);
638
- <a name="l00621"></a>00621 <span class="keywordflow">try</span> {
639
- <a name="l00622"></a>00622 <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 =
640
- <a name="l00623"></a>00623 <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);
641
- <a name="l00624"></a>00624 message.append(syse.<a class="code" href="classPassenger_1_1SystemException.html#0ef41d755fea2c9b1db2252e7c418dc8" title="Returns the system&amp;#39;s error message.">sys</a>());
642
- <a name="l00625"></a>00625 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> bad_cast &amp;) {
643
- <a name="l00626"></a>00626 message.append(e.what());
644
- <a name="l00627"></a>00627 }
645
- <a name="l00628"></a>00628 <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);
646
- <a name="l00629"></a>00629 } <span class="keywordflow">else</span> {
647
- <a name="l00630"></a>00630 list.erase(container-&gt;iterator);
648
- <a name="l00631"></a>00631 <span class="keywordflow">if</span> (list.empty()) {
649
- <a name="l00632"></a>00632 apps.erase(appRoot);
650
- <a name="l00633"></a>00633 appInstanceCount.erase(appRoot);
651
- <a name="l00634"></a>00634 }
652
- <a name="l00635"></a>00635 count--;
653
- <a name="l00636"></a>00636 active--;
654
- <a name="l00637"></a>00637 activeOrMaxChanged.notify_all();
655
- <a name="l00638"></a>00638 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
656
- <a name="l00639"></a>00639 <span class="stringliteral">"State is valid."</span>);
657
- <a name="l00640"></a>00640 }
658
- <a name="l00641"></a>00641 }
659
- <a name="l00642"></a>00642 }
660
- <a name="l00643"></a>00643 <span class="comment">// Never reached; shut up compiler warning</span>
661
- <a name="l00644"></a>00644 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>();
662
- <a name="l00645"></a>00645 }
663
- <a name="l00646"></a>00646
664
- <a name="l00647"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#bcf8faeb4f431ae07ea0e20270661d08">00647</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>() {
665
- <a name="l00648"></a>00648 mutex::scoped_lock l(lock);
666
- <a name="l00649"></a>00649 apps.clear();
667
- <a name="l00650"></a>00650 inactiveApps.clear();
668
- <a name="l00651"></a>00651 restartFileTimes.clear();
669
- <a name="l00652"></a>00652 appInstanceCount.clear();
670
- <a name="l00653"></a>00653 count = 0;
671
- <a name="l00654"></a>00654 active = 0;
672
- <a name="l00655"></a>00655 activeOrMaxChanged.notify_all();
673
- <a name="l00656"></a>00656 }
674
- <a name="l00657"></a>00657
675
- <a name="l00658"></a>00658 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
676
- <a name="l00659"></a>00659 mutex::scoped_lock l(lock);
677
- <a name="l00660"></a>00660 maxIdleTime = seconds;
678
- <a name="l00661"></a>00661 cleanerThreadSleeper.notify_one();
679
- <a name="l00662"></a>00662 }
680
- <a name="l00663"></a>00663
681
- <a name="l00664"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#04ef8c92da189520ad2022f4f82e9553">00664</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) {
682
- <a name="l00665"></a>00665 mutex::scoped_lock l(lock);
683
- <a name="l00666"></a>00666 this-&gt;max = max;
684
- <a name="l00667"></a>00667 activeOrMaxChanged.notify_all();
685
- <a name="l00668"></a>00668 }
686
- <a name="l00669"></a>00669
687
- <a name="l00670"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#7773c4a3dfbd88eac72401d063831788">00670</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>{
688
- <a name="l00671"></a>00671 <span class="keywordflow">return</span> active;
689
- <a name="l00672"></a>00672 }
690
- <a name="l00673"></a>00673
691
- <a name="l00674"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#cdbfe2b9ffacdab4438c879c2411bf02">00674</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>{
692
- <a name="l00675"></a>00675 <span class="keywordflow">return</span> count;
693
- <a name="l00676"></a>00676 }
694
- <a name="l00677"></a>00677
695
- <a name="l00678"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#3bafcda8d880f70561ad8a9da16e26ef">00678</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) {
696
- <a name="l00679"></a>00679 mutex::scoped_lock l(lock);
697
- <a name="l00680"></a>00680 this-&gt;maxPerApp = maxPerApp;
698
- <a name="l00681"></a>00681 activeOrMaxChanged.notify_all();
699
- <a name="l00682"></a>00682 }
700
- <a name="l00683"></a>00683
701
- <a name="l00684"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#e9c699b56f3a755ab10269c7fe585c2d">00684</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) {
702
- <a name="l00685"></a>00685 this-&gt;useGlobalQueue = value;
703
- <a name="l00686"></a>00686 }
704
- <a name="l00687"></a>00687
705
- <a name="l00688"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#6955152d237920988d20297d2fff5660">00688</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>{
706
- <a name="l00689"></a>00689 <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>();
707
- <a name="l00690"></a>00690 }
708
- <a name="l00691"></a>00691 <span class="comment"></span>
709
- <a name="l00692"></a>00692 <span class="comment"> /**</span>
710
- <a name="l00693"></a>00693 <span class="comment"> * Returns a textual description of the internal state of</span>
711
- <a name="l00694"></a>00694 <span class="comment"> * the application pool.</span>
712
- <a name="l00695"></a>00695 <span class="comment"> */</span>
713
- <a name="l00696"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383">00696</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>{
714
- <a name="l00697"></a>00697 <span class="keywordflow">if</span> (lockMutex) {
715
- <a name="l00698"></a>00698 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(boost::adopt_lock);
716
- <a name="l00699"></a>00699 } <span class="keywordflow">else</span> {
717
- <a name="l00700"></a>00700 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#gf6fab368d70c18fdf16bf5a24f630407" title="Convert anything to a string.">toString</a>(boost::defer_lock);
718
- <a name="l00701"></a>00701 }
719
- <a name="l00702"></a>00702 }
720
- <a name="l00703"></a>00703 };
721
- <a name="l00704"></a>00704
722
- <a name="l00705"></a>00705 } <span class="comment">// namespace Passenger</span>
723
- <a name="l00706"></a>00706
724
- <a name="l00707"></a>00707 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_STANDARD_APPLICATION_POOL_H_ */</span>
725
- <a name="l00708"></a>00708
106
+ <a name="l00090"></a>00090 <span class="comment"> * (Of course, StandardApplicationPool &lt;em&gt;is&lt;/em&gt; usable if each process creates its own</span>
107
+ <a name="l00091"></a>00091 <span class="comment"> * StandardApplicationPool object, but that would defeat the point of having a shared pool.)</span>
108
+ <a name="l00092"></a>00092 <span class="comment"> *</span>
109
+ <a name="l00093"></a>00093 <span class="comment"> * For multi-process environments, one should use ApplicationPoolServer instead.</span>
110
+ <a name="l00094"></a>00094 <span class="comment"> *</span>
111
+ <a name="l00095"></a>00095 <span class="comment"> * @ingroup Support</span>
112
+ <a name="l00096"></a>00096 <span class="comment"> */</span>
113
+ <a name="l00097"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html">00097</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> {
114
+ <a name="l00098"></a>00098 <span class="keyword">private</span>:
115
+ <a name="l00099"></a>00099 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_IDLE_TIME = 120;
116
+ <a name="l00100"></a>00100 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_POOL_SIZE = 20;
117
+ <a name="l00101"></a>00101 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> DEFAULT_MAX_INSTANCES_PER_APP = 0;
118
+ <a name="l00102"></a>00102 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> CLEANER_THREAD_STACK_SIZE = 1024 * 128;
119
+ <a name="l00103"></a>00103 <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> MAX_GET_ATTEMPTS = 10;
120
+ <a name="l00104"></a>00104 <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>
121
+ <a name="l00105"></a>00105
122
+ <a name="l00106"></a>00106 <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>;
123
+ <a name="l00107"></a>00107 <span class="keyword">struct </span>Domain;
124
+ <a name="l00108"></a>00108 <span class="keyword">struct </span>AppContainer;
125
+ <a name="l00109"></a>00109
126
+ <a name="l00110"></a>00110 <span class="keyword">typedef</span> shared_ptr&lt;Domain&gt; DomainPtr;
127
+ <a name="l00111"></a>00111 <span class="keyword">typedef</span> shared_ptr&lt;AppContainer&gt; AppContainerPtr;
128
+ <a name="l00112"></a>00112 <span class="keyword">typedef</span> list&lt;AppContainerPtr&gt; AppContainerList;
129
+ <a name="l00113"></a>00113 <span class="keyword">typedef</span> map&lt;string, DomainPtr&gt; DomainMap;
130
+ <a name="l00114"></a>00114
131
+ <a name="l00115"></a>00115 <span class="keyword">struct </span>Domain {
132
+ <a name="l00116"></a>00116 AppContainerList instances;
133
+ <a name="l00117"></a>00117 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size;
134
+ <a name="l00118"></a>00118 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> maxRequests;
135
+ <a name="l00119"></a>00119 <a class="code" href="classPassenger_1_1FileChecker.html" title="Utility class for checking for file changes.">FileChecker</a> restartFileChecker;
136
+ <a name="l00120"></a>00120 CachedFileStat alwaysRestartFileStatter;
137
+ <a name="l00121"></a>00121
138
+ <a name="l00122"></a>00122 Domain(<span class="keyword">const</span> <a class="code" href="structPassenger_1_1PoolOptions.html" title="This struct encapsulates information for ApplicationPool::get() and for SpawnManager::spawn()...">PoolOptions</a> &amp;options)
139
+ <a name="l00123"></a>00123 : restartFileChecker(determineRestartDir(options) + <span class="stringliteral">"/restart.txt"</span>),
140
+ <a name="l00124"></a>00124 alwaysRestartFileStatter(determineRestartDir(options) + <span class="stringliteral">"/always_restart.txt"</span>)
141
+ <a name="l00125"></a>00125 {
142
+ <a name="l00126"></a>00126 }
143
+ <a name="l00127"></a>00127
144
+ <a name="l00128"></a>00128 <span class="keyword">private</span>:
145
+ <a name="l00129"></a>00129 <span class="keyword">static</span> <span class="keywordtype">string</span> determineRestartDir(<span class="keyword">const</span> <a class="code" href="structPassenger_1_1PoolOptions.html" title="This struct encapsulates information for ApplicationPool::get() and for SpawnManager::spawn()...">PoolOptions</a> &amp;options) {
146
+ <a name="l00130"></a>00130 <span class="keywordflow">if</span> (options.<a class="code" href="structPassenger_1_1PoolOptions.html#b0f889f70a3ed22f2423d110ddaf26f5" title="The directory which contains restart.txt and always_restart.txt.">restartDir</a>.empty()) {
147
+ <a name="l00131"></a>00131 <span class="keywordflow">return</span> options.<a class="code" href="structPassenger_1_1PoolOptions.html#822039d204b48d9ed49184646734acf3" title="The root directory of the application to spawn.">appRoot</a> + <span class="stringliteral">"/tmp"</span>;
148
+ <a name="l00132"></a>00132 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (options.<a class="code" href="structPassenger_1_1PoolOptions.html#b0f889f70a3ed22f2423d110ddaf26f5" title="The directory which contains restart.txt and always_restart.txt.">restartDir</a>[0] == <span class="charliteral">'/'</span>) {
149
+ <a name="l00133"></a>00133 <span class="keywordflow">return</span> options.<a class="code" href="structPassenger_1_1PoolOptions.html#b0f889f70a3ed22f2423d110ddaf26f5" title="The directory which contains restart.txt and always_restart.txt.">restartDir</a>;
150
+ <a name="l00134"></a>00134 } <span class="keywordflow">else</span> {
151
+ <a name="l00135"></a>00135 <span class="keywordflow">return</span> options.<a class="code" href="structPassenger_1_1PoolOptions.html#822039d204b48d9ed49184646734acf3" title="The root directory of the application to spawn.">appRoot</a> + <span class="stringliteral">"/"</span> + options.<a class="code" href="structPassenger_1_1PoolOptions.html#b0f889f70a3ed22f2423d110ddaf26f5" title="The directory which contains restart.txt and always_restart.txt.">restartDir</a>;
152
+ <a name="l00136"></a>00136 }
153
+ <a name="l00137"></a>00137 }
154
+ <a name="l00138"></a>00138 };
155
+ <a name="l00139"></a>00139
156
+ <a name="l00140"></a>00140 <span class="keyword">struct </span>AppContainer {
157
+ <a name="l00141"></a>00141 ApplicationPtr app;
158
+ <a name="l00142"></a>00142 time_t startTime;
159
+ <a name="l00143"></a>00143 time_t lastUsed;
160
+ <a name="l00144"></a>00144 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> sessions;
161
+ <a name="l00145"></a>00145 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> processed;
162
+ <a name="l00146"></a>00146 AppContainerList::iterator iterator;
163
+ <a name="l00147"></a>00147 AppContainerList::iterator ia_iterator;
164
+ <a name="l00148"></a>00148
165
+ <a name="l00149"></a>00149 AppContainer() {
166
+ <a name="l00150"></a>00150 startTime = time(NULL);
167
+ <a name="l00151"></a>00151 processed = 0;
168
+ <a name="l00152"></a>00152 }
169
+ <a name="l00153"></a>00153 <span class="comment"></span>
170
+ <a name="l00154"></a>00154 <span class="comment"> /**</span>
171
+ <a name="l00155"></a>00155 <span class="comment"> * Returns the uptime of this AppContainer so far, as a string.</span>
172
+ <a name="l00156"></a>00156 <span class="comment"> */</span>
173
+ <a name="l00157"></a>00157 <span class="keywordtype">string</span> uptime()<span class="keyword"> const </span>{
174
+ <a name="l00158"></a>00158 time_t seconds = time(NULL) - startTime;
175
+ <a name="l00159"></a>00159 stringstream result;
176
+ <a name="l00160"></a>00160
177
+ <a name="l00161"></a>00161 <span class="keywordflow">if</span> (seconds &gt;= 60) {
178
+ <a name="l00162"></a>00162 time_t minutes = seconds / 60;
179
+ <a name="l00163"></a>00163 <span class="keywordflow">if</span> (minutes &gt;= 60) {
180
+ <a name="l00164"></a>00164 time_t hours = minutes / 60;
181
+ <a name="l00165"></a>00165 minutes = minutes % 60;
182
+ <a name="l00166"></a>00166 result &lt;&lt; hours &lt;&lt; <span class="stringliteral">"h "</span>;
183
+ <a name="l00167"></a>00167 }
184
+ <a name="l00168"></a>00168
185
+ <a name="l00169"></a>00169 seconds = seconds % 60;
186
+ <a name="l00170"></a>00170 result &lt;&lt; minutes &lt;&lt; <span class="stringliteral">"m "</span>;
187
+ <a name="l00171"></a>00171 }
188
+ <a name="l00172"></a>00172 result &lt;&lt; seconds &lt;&lt; <span class="stringliteral">"s"</span>;
189
+ <a name="l00173"></a>00173 <span class="keywordflow">return</span> result.str();
190
+ <a name="l00174"></a>00174 }
191
+ <a name="l00175"></a>00175 };
192
+ <a name="l00176"></a>00176 <span class="comment"></span>
193
+ <a name="l00177"></a>00177 <span class="comment"> /**</span>
194
+ <a name="l00178"></a>00178 <span class="comment"> * A data structure which contains data that's shared between a</span>
195
+ <a name="l00179"></a>00179 <span class="comment"> * StandardApplicationPool and a SessionCloseCallback object.</span>
196
+ <a name="l00180"></a>00180 <span class="comment"> * This is because the StandardApplicationPool's life time could be</span>
197
+ <a name="l00181"></a>00181 <span class="comment"> * different from a SessionCloseCallback's.</span>
198
+ <a name="l00182"></a>00182 <span class="comment"> */</span>
199
+ <a name="l00183"></a>00183 <span class="keyword">struct </span>SharedData {
200
+ <a name="l00184"></a>00184 boost::mutex lock;
201
+ <a name="l00185"></a>00185 condition activeOrMaxChanged;
202
+ <a name="l00186"></a>00186
203
+ <a name="l00187"></a>00187 DomainMap domains;
204
+ <a name="l00188"></a>00188 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> max;
205
+ <a name="l00189"></a>00189 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count;
206
+ <a name="l00190"></a>00190 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> active;
207
+ <a name="l00191"></a>00191 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxPerApp;
208
+ <a name="l00192"></a>00192 AppContainerList inactiveApps;
209
+ <a name="l00193"></a>00193 map&lt;string, unsigned int&gt; appInstanceCount;
210
+ <a name="l00194"></a>00194 };
211
+ <a name="l00195"></a>00195
212
+ <a name="l00196"></a>00196 <span class="keyword">typedef</span> shared_ptr&lt;SharedData&gt; SharedDataPtr;
213
+ <a name="l00197"></a>00197 <span class="comment"></span>
214
+ <a name="l00198"></a>00198 <span class="comment"> /**</span>
215
+ <a name="l00199"></a>00199 <span class="comment"> * Function object which will be called when a session has been closed.</span>
216
+ <a name="l00200"></a>00200 <span class="comment"> */</span>
217
+ <a name="l00201"></a>00201 <span class="keyword">struct </span>SessionCloseCallback {
218
+ <a name="l00202"></a>00202 SharedDataPtr data;
219
+ <a name="l00203"></a>00203 weak_ptr&lt;AppContainer&gt; container;
220
+ <a name="l00204"></a>00204
221
+ <a name="l00205"></a>00205 SessionCloseCallback(SharedDataPtr data,
222
+ <a name="l00206"></a>00206 <span class="keyword">const</span> weak_ptr&lt;AppContainer&gt; &amp;container) {
223
+ <a name="l00207"></a>00207 this-&gt;data = data;
224
+ <a name="l00208"></a>00208 this-&gt;container = container;
225
+ <a name="l00209"></a>00209 }
226
+ <a name="l00210"></a>00210
227
+ <a name="l00211"></a>00211 <span class="keywordtype">void</span> operator()() {
228
+ <a name="l00212"></a>00212 boost::mutex::scoped_lock l(data-&gt;lock);
229
+ <a name="l00213"></a>00213 AppContainerPtr container(this-&gt;container.lock());
230
+ <a name="l00214"></a>00214
231
+ <a name="l00215"></a>00215 <span class="keywordflow">if</span> (container == NULL) {
232
+ <a name="l00216"></a>00216 <span class="keywordflow">return</span>;
233
+ <a name="l00217"></a>00217 }
234
+ <a name="l00218"></a>00218
235
+ <a name="l00219"></a>00219 DomainMap::iterator it;
236
+ <a name="l00220"></a>00220 it = data-&gt;domains.find(container-&gt;app-&gt;getAppRoot());
237
+ <a name="l00221"></a>00221 <span class="keywordflow">if</span> (it != data-&gt;domains.end()) {
238
+ <a name="l00222"></a>00222 Domain *domain = it-&gt;second.get();
239
+ <a name="l00223"></a>00223 AppContainerList *instances = &amp;domain-&gt;instances;
240
+ <a name="l00224"></a>00224
241
+ <a name="l00225"></a>00225 container-&gt;processed++;
242
+ <a name="l00226"></a>00226 <span class="keywordflow">if</span> (domain-&gt;maxRequests &gt; 0 &amp;&amp; container-&gt;processed &gt;= domain-&gt;maxRequests) {
243
+ <a name="l00227"></a>00227 instances-&gt;erase(container-&gt;iterator);
244
+ <a name="l00228"></a>00228 domain-&gt;size--;
245
+ <a name="l00229"></a>00229 <span class="keywordflow">if</span> (instances-&gt;empty()) {
246
+ <a name="l00230"></a>00230 data-&gt;domains.erase(container-&gt;app-&gt;getAppRoot());
247
+ <a name="l00231"></a>00231 }
248
+ <a name="l00232"></a>00232 data-&gt;count--;
249
+ <a name="l00233"></a>00233 data-&gt;active--;
250
+ <a name="l00234"></a>00234 data-&gt;activeOrMaxChanged.notify_all();
251
+ <a name="l00235"></a>00235 } <span class="keywordflow">else</span> {
252
+ <a name="l00236"></a>00236 container-&gt;lastUsed = time(NULL);
253
+ <a name="l00237"></a>00237 container-&gt;sessions--;
254
+ <a name="l00238"></a>00238 <span class="keywordflow">if</span> (container-&gt;sessions == 0) {
255
+ <a name="l00239"></a>00239 instances-&gt;erase(container-&gt;iterator);
256
+ <a name="l00240"></a>00240 instances-&gt;push_front(container);
257
+ <a name="l00241"></a>00241 container-&gt;iterator = instances-&gt;begin();
258
+ <a name="l00242"></a>00242 data-&gt;inactiveApps.push_back(container);
259
+ <a name="l00243"></a>00243 container-&gt;ia_iterator = data-&gt;inactiveApps.end();
260
+ <a name="l00244"></a>00244 container-&gt;ia_iterator--;
261
+ <a name="l00245"></a>00245 data-&gt;active--;
262
+ <a name="l00246"></a>00246 data-&gt;activeOrMaxChanged.notify_all();
263
+ <a name="l00247"></a>00247 }
264
+ <a name="l00248"></a>00248 }
265
+ <a name="l00249"></a>00249 }
266
+ <a name="l00250"></a>00250 }
267
+ <a name="l00251"></a>00251 };
268
+ <a name="l00252"></a>00252
269
+ <a name="l00253"></a>00253 <span class="preprocessor"> #ifdef PASSENGER_USE_DUMMY_SPAWN_MANAGER</span>
270
+ <a name="l00254"></a>00254 <span class="preprocessor"></span> <a class="code" href="classPassenger_1_1DummySpawnManager.html" title="A dummy SpawnManager replacement for testing/debugging purposes.">DummySpawnManager</a> spawnManager;
271
+ <a name="l00255"></a>00255 <span class="preprocessor"> #else</span>
272
+ <a name="l00256"></a>00256 <span class="preprocessor"></span> <a class="code" href="classPassenger_1_1SpawnManager.html" title="Spawning of Ruby on Rails/Rack application instances.">SpawnManager</a> spawnManager;
273
+ <a name="l00257"></a>00257 <span class="preprocessor"> #endif</span>
274
+ <a name="l00258"></a>00258 <span class="preprocessor"></span> SharedDataPtr data;
275
+ <a name="l00259"></a>00259 boost::thread *cleanerThread;
276
+ <a name="l00260"></a>00260 <span class="keywordtype">bool</span> detached;
277
+ <a name="l00261"></a>00261 <span class="keywordtype">bool</span> done;
278
+ <a name="l00262"></a>00262 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxIdleTime;
279
+ <a name="l00263"></a>00263 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> waitingOnGlobalQueue;
280
+ <a name="l00264"></a>00264 condition cleanerThreadSleeper;
281
+ <a name="l00265"></a>00265
282
+ <a name="l00266"></a>00266 <span class="comment">// Shortcuts for instance variables in SharedData. Saves typing in get().</span>
283
+ <a name="l00267"></a>00267 boost::mutex &amp;lock;
284
+ <a name="l00268"></a>00268 condition &amp;activeOrMaxChanged;
285
+ <a name="l00269"></a>00269 DomainMap &amp;domains;
286
+ <a name="l00270"></a>00270 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;max;
287
+ <a name="l00271"></a>00271 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;count;
288
+ <a name="l00272"></a>00272 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;active;
289
+ <a name="l00273"></a>00273 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;maxPerApp;
290
+ <a name="l00274"></a>00274 AppContainerList &amp;inactiveApps;
291
+ <a name="l00275"></a>00275 map&lt;string, unsigned int&gt; &amp;appInstanceCount;
292
+ <a name="l00276"></a>00276 <span class="comment"></span>
293
+ <a name="l00277"></a>00277 <span class="comment"> /**</span>
294
+ <a name="l00278"></a>00278 <span class="comment"> * Verify that all the invariants are correct.</span>
295
+ <a name="l00279"></a>00279 <span class="comment"> */</span>
296
+ <a name="l00280"></a>00280 <span class="keywordtype">bool</span> <span class="keyword">inline</span> verifyState() {
297
+ <a name="l00281"></a>00281 <span class="preprocessor"> #if PASSENGER_DEBUG</span>
298
+ <a name="l00282"></a>00282 <span class="preprocessor"></span> <span class="comment">// Invariants for _domains_.</span>
299
+ <a name="l00283"></a>00283 DomainMap::const_iterator it;
300
+ <a name="l00284"></a>00284 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> totalSize = 0;
301
+ <a name="l00285"></a>00285 <span class="keywordflow">for</span> (it = domains.begin(); it != domains.end(); it++) {
302
+ <a name="l00286"></a>00286 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot = it-&gt;first;
303
+ <a name="l00287"></a>00287 Domain *domain = it-&gt;second.get();
304
+ <a name="l00288"></a>00288 AppContainerList *instances = &amp;domain-&gt;instances;
305
+ <a name="l00289"></a>00289
306
+ <a name="l00290"></a>00290 P_ASSERT(domain-&gt;size &lt;= count, <span class="keyword">false</span>,
307
+ <a name="l00291"></a>00291 <span class="stringliteral">"domains['"</span> &lt;&lt; appRoot &lt;&lt; <span class="stringliteral">"'].size ("</span> &lt;&lt; domain-&gt;size &lt;&lt;
308
+ <a name="l00292"></a>00292 <span class="stringliteral">") &lt;= count ("</span> &lt;&lt; count &lt;&lt; <span class="stringliteral">")"</span>);
309
+ <a name="l00293"></a>00293 totalSize += domain-&gt;size;
310
+ <a name="l00294"></a>00294
311
+ <a name="l00295"></a>00295 <span class="comment">// Invariants for Domain.</span>
312
+ <a name="l00296"></a>00296
313
+ <a name="l00297"></a>00297 P_ASSERT(!instances-&gt;empty(), <span class="keyword">false</span>,
314
+ <a name="l00298"></a>00298 <span class="stringliteral">"domains['"</span> &lt;&lt; appRoot &lt;&lt; <span class="stringliteral">"'].instances is nonempty."</span>);
315
+ <a name="l00299"></a>00299
316
+ <a name="l00300"></a>00300 AppContainerList::const_iterator prev_lit;
317
+ <a name="l00301"></a>00301 AppContainerList::const_iterator lit;
318
+ <a name="l00302"></a>00302 prev_lit = instances-&gt;begin();
319
+ <a name="l00303"></a>00303 lit = prev_lit;
320
+ <a name="l00304"></a>00304 lit++;
321
+ <a name="l00305"></a>00305 <span class="keywordflow">for</span> (; lit != instances-&gt;end(); lit++) {
322
+ <a name="l00306"></a>00306 <span class="keywordflow">if</span> ((*prev_lit)-&gt;sessions &gt; 0) {
323
+ <a name="l00307"></a>00307 P_ASSERT((*lit)-&gt;sessions &gt; 0, <span class="keyword">false</span>,
324
+ <a name="l00308"></a>00308 <span class="stringliteral">"domains['"</span> &lt;&lt; appRoot &lt;&lt; <span class="stringliteral">"'].instances "</span>
325
+ <a name="l00309"></a>00309 <span class="stringliteral">"is sorted from nonactive to active"</span>);
326
+ <a name="l00310"></a>00310 }
327
+ <a name="l00311"></a>00311 }
328
+ <a name="l00312"></a>00312 }
329
+ <a name="l00313"></a>00313 P_ASSERT(totalSize == count, <span class="keyword">false</span>, <span class="stringliteral">"(sum of all d.size in domains) == count"</span>);
330
+ <a name="l00314"></a>00314
331
+ <a name="l00315"></a>00315 P_ASSERT(active &lt;= count, <span class="keyword">false</span>,
332
+ <a name="l00316"></a>00316 <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>);
333
+ <a name="l00317"></a>00317 P_ASSERT(inactiveApps.size() == count - active, <span class="keyword">false</span>,
334
+ <a name="l00318"></a>00318 <span class="stringliteral">"inactive_apps.size() == count - active"</span>);
335
+ <a name="l00319"></a>00319 <span class="preprocessor"> #endif</span>
336
+ <a name="l00320"></a>00320 <span class="preprocessor"></span> <span class="keywordflow">return</span> <span class="keyword">true</span>;
337
+ <a name="l00321"></a>00321 }
338
+ <a name="l00322"></a>00322
339
+ <a name="l00323"></a>00323 <span class="keywordtype">string</span> toStringWithoutLock()<span class="keyword"> const </span>{
340
+ <a name="l00324"></a>00324 stringstream result;
341
+ <a name="l00325"></a>00325
342
+ <a name="l00326"></a>00326 result &lt;&lt; <span class="stringliteral">"----------- General information -----------"</span> &lt;&lt; endl;
343
+ <a name="l00327"></a>00327 result &lt;&lt; <span class="stringliteral">"max = "</span> &lt;&lt; max &lt;&lt; endl;
344
+ <a name="l00328"></a>00328 result &lt;&lt; <span class="stringliteral">"count = "</span> &lt;&lt; count &lt;&lt; endl;
345
+ <a name="l00329"></a>00329 result &lt;&lt; <span class="stringliteral">"active = "</span> &lt;&lt; active &lt;&lt; endl;
346
+ <a name="l00330"></a>00330 result &lt;&lt; <span class="stringliteral">"inactive = "</span> &lt;&lt; inactiveApps.size() &lt;&lt; endl;
347
+ <a name="l00331"></a>00331 result &lt;&lt; <span class="stringliteral">"Waiting on global queue: "</span> &lt;&lt; waitingOnGlobalQueue &lt;&lt; endl;
348
+ <a name="l00332"></a>00332 result &lt;&lt; endl;
349
+ <a name="l00333"></a>00333
350
+ <a name="l00334"></a>00334 result &lt;&lt; <span class="stringliteral">"----------- Domains -----------"</span> &lt;&lt; endl;
351
+ <a name="l00335"></a>00335 DomainMap::const_iterator it;
352
+ <a name="l00336"></a>00336 <span class="keywordflow">for</span> (it = domains.begin(); it != domains.end(); it++) {
353
+ <a name="l00337"></a>00337 Domain *domain = it-&gt;second.get();
354
+ <a name="l00338"></a>00338 AppContainerList *instances = &amp;domain-&gt;instances;
355
+ <a name="l00339"></a>00339 AppContainerList::const_iterator lit;
356
+ <a name="l00340"></a>00340
357
+ <a name="l00341"></a>00341 result &lt;&lt; it-&gt;first &lt;&lt; <span class="stringliteral">": "</span> &lt;&lt; endl;
358
+ <a name="l00342"></a>00342 <span class="keywordflow">for</span> (lit = instances-&gt;begin(); lit != instances-&gt;end(); lit++) {
359
+ <a name="l00343"></a>00343 AppContainer *container = lit-&gt;get();
360
+ <a name="l00344"></a>00344 <span class="keywordtype">char</span> buf[128];
361
+ <a name="l00345"></a>00345
362
+ <a name="l00346"></a>00346 snprintf(buf, <span class="keyword">sizeof</span>(buf),
363
+ <a name="l00347"></a>00347 <span class="stringliteral">"PID: %-5lu Sessions: %-2u Processed: %-5u Uptime: %s"</span>,
364
+ <a name="l00348"></a>00348 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) container-&gt;app-&gt;getPid(),
365
+ <a name="l00349"></a>00349 container-&gt;sessions,
366
+ <a name="l00350"></a>00350 container-&gt;processed,
367
+ <a name="l00351"></a>00351 container-&gt;uptime().c_str());
368
+ <a name="l00352"></a>00352 result &lt;&lt; <span class="stringliteral">" "</span> &lt;&lt; buf &lt;&lt; endl;
369
+ <a name="l00353"></a>00353 }
370
+ <a name="l00354"></a>00354 result &lt;&lt; endl;
371
+ <a name="l00355"></a>00355 }
372
+ <a name="l00356"></a>00356 <span class="keywordflow">return</span> result.str();
373
+ <a name="l00357"></a>00357 }
374
+ <a name="l00358"></a>00358
375
+ <a name="l00359"></a>00359 <span class="keywordtype">bool</span> needsRestart(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot, Domain *domain, <span class="keyword">const</span> <a class="code" href="structPassenger_1_1PoolOptions.html" title="This struct encapsulates information for ApplicationPool::get() and for SpawnManager::spawn()...">PoolOptions</a> &amp;options) {
376
+ <a name="l00360"></a>00360 <span class="keywordflow">return</span> domain-&gt;alwaysRestartFileStatter.refresh(options.<a class="code" href="structPassenger_1_1PoolOptions.html#eaf5a998b4a5da2246685c2dfb8a8c6d" title="A throttling rate for file stats.">statThrottleRate</a>) == 0
377
+ <a name="l00361"></a>00361 || domain-&gt;restartFileChecker.changed(options.<a class="code" href="structPassenger_1_1PoolOptions.html#eaf5a998b4a5da2246685c2dfb8a8c6d" title="A throttling rate for file stats.">statThrottleRate</a>);
378
+ <a name="l00362"></a>00362 }
379
+ <a name="l00363"></a>00363
380
+ <a name="l00364"></a>00364 <span class="keywordtype">void</span> cleanerThreadMainLoop() {
381
+ <a name="l00365"></a>00365 this_thread::disable_syscall_interruption dsi;
382
+ <a name="l00366"></a>00366 unique_lock&lt;boost::mutex&gt; l(lock);
383
+ <a name="l00367"></a>00367 <span class="keywordflow">try</span> {
384
+ <a name="l00368"></a>00368 <span class="keywordflow">while</span> (!done &amp;&amp; !this_thread::interruption_requested()) {
385
+ <a name="l00369"></a>00369 xtime xt;
386
+ <a name="l00370"></a>00370 xtime_get(&amp;xt, TIME_UTC);
387
+ <a name="l00371"></a>00371 xt.sec += maxIdleTime + 1;
388
+ <a name="l00372"></a>00372 <span class="keywordflow">if</span> (cleanerThreadSleeper.timed_wait(l, xt)) {
389
+ <a name="l00373"></a>00373 <span class="comment">// Condition was woken up.</span>
390
+ <a name="l00374"></a>00374 <span class="keywordflow">if</span> (done) {
391
+ <a name="l00375"></a>00375 <span class="comment">// StandardApplicationPool is being destroyed.</span>
392
+ <a name="l00376"></a>00376 <span class="keywordflow">break</span>;
393
+ <a name="l00377"></a>00377 } <span class="keywordflow">else</span> {
394
+ <a name="l00378"></a>00378 <span class="comment">// maxIdleTime changed.</span>
395
+ <a name="l00379"></a>00379 <span class="keywordflow">continue</span>;
396
+ <a name="l00380"></a>00380 }
397
+ <a name="l00381"></a>00381 }
398
+ <a name="l00382"></a>00382
399
+ <a name="l00383"></a>00383 time_t now = syscalls::time(NULL);
400
+ <a name="l00384"></a>00384 AppContainerList::iterator it;
401
+ <a name="l00385"></a>00385 <span class="keywordflow">for</span> (it = inactiveApps.begin(); it != inactiveApps.end(); it++) {
402
+ <a name="l00386"></a>00386 AppContainer &amp;container(*it-&gt;get());
403
+ <a name="l00387"></a>00387 ApplicationPtr app(container.app);
404
+ <a name="l00388"></a>00388 Domain *domain = domains[app-&gt;getAppRoot()].get();
405
+ <a name="l00389"></a>00389 AppContainerList *instances = &amp;domain-&gt;instances;
406
+ <a name="l00390"></a>00390
407
+ <a name="l00391"></a>00391 <span class="keywordflow">if</span> (maxIdleTime &gt; 0 &amp;&amp;
408
+ <a name="l00392"></a>00392 (now - container.lastUsed &gt; (time_t) maxIdleTime)) {
409
+ <a name="l00393"></a>00393 P_DEBUG(<span class="stringliteral">"Cleaning idle app "</span> &lt;&lt; app-&gt;getAppRoot() &lt;&lt;
410
+ <a name="l00394"></a>00394 <span class="stringliteral">" (PID "</span> &lt;&lt; app-&gt;getPid() &lt;&lt; <span class="stringliteral">")"</span>);
411
+ <a name="l00395"></a>00395 instances-&gt;erase(container.iterator);
412
+ <a name="l00396"></a>00396
413
+ <a name="l00397"></a>00397 AppContainerList::iterator prev = it;
414
+ <a name="l00398"></a>00398 prev--;
415
+ <a name="l00399"></a>00399 inactiveApps.erase(it);
416
+ <a name="l00400"></a>00400 it = prev;
417
+ <a name="l00401"></a>00401
418
+ <a name="l00402"></a>00402 domain-&gt;size--;
419
+ <a name="l00403"></a>00403
420
+ <a name="l00404"></a>00404 count--;
421
+ <a name="l00405"></a>00405 }
422
+ <a name="l00406"></a>00406 <span class="keywordflow">if</span> (instances-&gt;empty()) {
423
+ <a name="l00407"></a>00407 domains.erase(app-&gt;getAppRoot());
424
+ <a name="l00408"></a>00408 }
425
+ <a name="l00409"></a>00409 }
426
+ <a name="l00410"></a>00410 }
427
+ <a name="l00411"></a>00411 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
428
+ <a name="l00412"></a>00412 P_ERROR(<span class="stringliteral">"Uncaught exception: "</span> &lt;&lt; e.what());
429
+ <a name="l00413"></a>00413 }
430
+ <a name="l00414"></a>00414 }
431
+ <a name="l00415"></a>00415 <span class="comment"></span>
432
+ <a name="l00416"></a>00416 <span class="comment"> /**</span>
433
+ <a name="l00417"></a>00417 <span class="comment"> * Spawn a new application instance, or use an existing one that's in the pool.</span>
434
+ <a name="l00418"></a>00418 <span class="comment"> *</span>
435
+ <a name="l00419"></a>00419 <span class="comment"> * @throws boost::thread_interrupted</span>
436
+ <a name="l00420"></a>00420 <span class="comment"> * @throws SpawnException</span>
437
+ <a name="l00421"></a>00421 <span class="comment"> * @throws SystemException</span>
438
+ <a name="l00422"></a>00422 <span class="comment"> */</span>
439
+ <a name="l00423"></a>00423 pair&lt;AppContainerPtr, Domain *&gt;
440
+ <a name="l00424"></a>00424 spawnOrUseExisting(boost::mutex::scoped_lock &amp;l, <span class="keyword">const</span> <a class="code" href="structPassenger_1_1PoolOptions.html" title="This struct encapsulates information for ApplicationPool::get() and for SpawnManager::spawn()...">PoolOptions</a> &amp;options) {
441
+ <a name="l00425"></a>00425 beginning_of_function:
442
+ <a name="l00426"></a>00426
443
+ <a name="l00427"></a>00427 TRACE_POINT();
444
+ <a name="l00428"></a>00428 this_thread::disable_interruption di;
445
+ <a name="l00429"></a>00429 this_thread::disable_syscall_interruption dsi;
446
+ <a name="l00430"></a>00430 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot(options.<a class="code" href="structPassenger_1_1PoolOptions.html#822039d204b48d9ed49184646734acf3" title="The root directory of the application to spawn.">appRoot</a>);
447
+ <a name="l00431"></a>00431 AppContainerPtr container;
448
+ <a name="l00432"></a>00432 Domain *domain;
449
+ <a name="l00433"></a>00433 AppContainerList *instances;
450
+ <a name="l00434"></a>00434
451
+ <a name="l00435"></a>00435 <span class="keywordflow">try</span> {
452
+ <a name="l00436"></a>00436 DomainMap::iterator it(domains.find(appRoot));
453
+ <a name="l00437"></a>00437
454
+ <a name="l00438"></a>00438 <span class="keywordflow">if</span> (it != domains.end() &amp;&amp; needsRestart(appRoot, it-&gt;second.get(), options)) {
455
+ <a name="l00439"></a>00439 AppContainerList::iterator it2;
456
+ <a name="l00440"></a>00440 instances = &amp;it-&gt;second-&gt;instances;
457
+ <a name="l00441"></a>00441 <span class="keywordflow">for</span> (it2 = instances-&gt;begin(); it2 != instances-&gt;end(); it2++) {
458
+ <a name="l00442"></a>00442 container = *it2;
459
+ <a name="l00443"></a>00443 <span class="keywordflow">if</span> (container-&gt;sessions == 0) {
460
+ <a name="l00444"></a>00444 inactiveApps.erase(container-&gt;ia_iterator);
461
+ <a name="l00445"></a>00445 } <span class="keywordflow">else</span> {
462
+ <a name="l00446"></a>00446 active--;
463
+ <a name="l00447"></a>00447 }
464
+ <a name="l00448"></a>00448 it2--;
465
+ <a name="l00449"></a>00449 instances-&gt;erase(container-&gt;iterator);
466
+ <a name="l00450"></a>00450 count--;
467
+ <a name="l00451"></a>00451 }
468
+ <a name="l00452"></a>00452 domains.erase(appRoot);
469
+ <a name="l00453"></a>00453 spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#2e85c43042b9556ca2fd74b8d28956ce" title="Remove the cached application instances at the given application root.">reload</a>(appRoot);
470
+ <a name="l00454"></a>00454 it = domains.end();
471
+ <a name="l00455"></a>00455 activeOrMaxChanged.notify_all();
472
+ <a name="l00456"></a>00456 }
473
+ <a name="l00457"></a>00457
474
+ <a name="l00458"></a>00458 <span class="keywordflow">if</span> (it != domains.end()) {
475
+ <a name="l00459"></a>00459 domain = it-&gt;second.get();
476
+ <a name="l00460"></a>00460 instances = &amp;domain-&gt;instances;
477
+ <a name="l00461"></a>00461
478
+ <a name="l00462"></a>00462 <span class="keywordflow">if</span> (instances-&gt;front()-&gt;sessions == 0) {
479
+ <a name="l00463"></a>00463 container = instances-&gt;front();
480
+ <a name="l00464"></a>00464 instances-&gt;pop_front();
481
+ <a name="l00465"></a>00465 instances-&gt;push_back(container);
482
+ <a name="l00466"></a>00466 container-&gt;iterator = instances-&gt;end();
483
+ <a name="l00467"></a>00467 container-&gt;iterator--;
484
+ <a name="l00468"></a>00468 inactiveApps.erase(container-&gt;ia_iterator);
485
+ <a name="l00469"></a>00469 active++;
486
+ <a name="l00470"></a>00470 activeOrMaxChanged.notify_all();
487
+ <a name="l00471"></a>00471 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (count &gt;= max || (
488
+ <a name="l00472"></a>00472 maxPerApp != 0 &amp;&amp; domain-&gt;size &gt;= maxPerApp )
489
+ <a name="l00473"></a>00473 ) {
490
+ <a name="l00474"></a>00474 <span class="keywordflow">if</span> (options.<a class="code" href="structPassenger_1_1PoolOptions.html#b610e568a7b5d3bb27460d6e35952b7e" title="Whether to use a global queue instead of a per-backend process queue.">useGlobalQueue</a>) {
491
+ <a name="l00475"></a>00475 UPDATE_TRACE_POINT();
492
+ <a name="l00476"></a>00476 waitingOnGlobalQueue++;
493
+ <a name="l00477"></a>00477 activeOrMaxChanged.wait(l);
494
+ <a name="l00478"></a>00478 waitingOnGlobalQueue--;
495
+ <a name="l00479"></a>00479 <span class="keywordflow">goto</span> beginning_of_function;
496
+ <a name="l00480"></a>00480 } <span class="keywordflow">else</span> {
497
+ <a name="l00481"></a>00481 AppContainerList::iterator it(instances-&gt;begin());
498
+ <a name="l00482"></a>00482 AppContainerList::iterator smallest(instances-&gt;begin());
499
+ <a name="l00483"></a>00483 it++;
500
+ <a name="l00484"></a>00484 <span class="keywordflow">for</span> (; it != instances-&gt;end(); it++) {
501
+ <a name="l00485"></a>00485 <span class="keywordflow">if</span> ((*it)-&gt;sessions &lt; (*smallest)-&gt;sessions) {
502
+ <a name="l00486"></a>00486 smallest = it;
503
+ <a name="l00487"></a>00487 }
504
+ <a name="l00488"></a>00488 }
505
+ <a name="l00489"></a>00489 container = *smallest;
506
+ <a name="l00490"></a>00490 instances-&gt;erase(smallest);
507
+ <a name="l00491"></a>00491 instances-&gt;push_back(container);
508
+ <a name="l00492"></a>00492 container-&gt;iterator = instances-&gt;end();
509
+ <a name="l00493"></a>00493 container-&gt;iterator--;
510
+ <a name="l00494"></a>00494 }
511
+ <a name="l00495"></a>00495 } <span class="keywordflow">else</span> {
512
+ <a name="l00496"></a>00496 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());
513
+ <a name="l00497"></a>00497 {
514
+ <a name="l00498"></a>00498 this_thread::restore_interruption ri(di);
515
+ <a name="l00499"></a>00499 this_thread::restore_syscall_interruption rsi(dsi);
516
+ <a name="l00500"></a>00500 container-&gt;app = spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#af035d564cc4e6683508939c9d6dbb64" title="Spawn a new instance of an application.">spawn</a>(options);
517
+ <a name="l00501"></a>00501 }
518
+ <a name="l00502"></a>00502 container-&gt;sessions = 0;
519
+ <a name="l00503"></a>00503 instances-&gt;push_back(container);
520
+ <a name="l00504"></a>00504 container-&gt;iterator = instances-&gt;end();
521
+ <a name="l00505"></a>00505 container-&gt;iterator--;
522
+ <a name="l00506"></a>00506 domain-&gt;size++;
523
+ <a name="l00507"></a>00507 count++;
524
+ <a name="l00508"></a>00508 active++;
525
+ <a name="l00509"></a>00509 activeOrMaxChanged.notify_all();
526
+ <a name="l00510"></a>00510 }
527
+ <a name="l00511"></a>00511 } <span class="keywordflow">else</span> {
528
+ <a name="l00512"></a>00512 <span class="keywordflow">if</span> (active &gt;= max) {
529
+ <a name="l00513"></a>00513 UPDATE_TRACE_POINT();
530
+ <a name="l00514"></a>00514 activeOrMaxChanged.wait(l);
531
+ <a name="l00515"></a>00515 <span class="keywordflow">goto</span> beginning_of_function;
532
+ <a name="l00516"></a>00516 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (count == max) {
533
+ <a name="l00517"></a>00517 container = inactiveApps.front();
534
+ <a name="l00518"></a>00518 inactiveApps.pop_front();
535
+ <a name="l00519"></a>00519 domain = domains[container-&gt;app-&gt;getAppRoot()].get();
536
+ <a name="l00520"></a>00520 instances = &amp;domain-&gt;instances;
537
+ <a name="l00521"></a>00521 instances-&gt;erase(container-&gt;iterator);
538
+ <a name="l00522"></a>00522 <span class="keywordflow">if</span> (instances-&gt;empty()) {
539
+ <a name="l00523"></a>00523 domains.erase(container-&gt;app-&gt;getAppRoot());
540
+ <a name="l00524"></a>00524 } <span class="keywordflow">else</span> {
541
+ <a name="l00525"></a>00525 domain-&gt;size--;
542
+ <a name="l00526"></a>00526 }
543
+ <a name="l00527"></a>00527 count--;
544
+ <a name="l00528"></a>00528 }
545
+ <a name="l00529"></a>00529
546
+ <a name="l00530"></a>00530 UPDATE_TRACE_POINT();
547
+ <a name="l00531"></a>00531 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());
548
+ <a name="l00532"></a>00532 {
549
+ <a name="l00533"></a>00533 this_thread::restore_interruption ri(di);
550
+ <a name="l00534"></a>00534 this_thread::restore_syscall_interruption rsi(dsi);
551
+ <a name="l00535"></a>00535 container-&gt;app = spawnManager.<a class="code" href="classPassenger_1_1SpawnManager.html#af035d564cc4e6683508939c9d6dbb64" title="Spawn a new instance of an application.">spawn</a>(options);
552
+ <a name="l00536"></a>00536 }
553
+ <a name="l00537"></a>00537 container-&gt;sessions = 0;
554
+ <a name="l00538"></a>00538 it = domains.find(appRoot);
555
+ <a name="l00539"></a>00539 <span class="keywordflow">if</span> (it == domains.end()) {
556
+ <a name="l00540"></a>00540 domain = <span class="keyword">new</span> Domain(options);
557
+ <a name="l00541"></a>00541 domain-&gt;size = 1;
558
+ <a name="l00542"></a>00542 domain-&gt;maxRequests = options.<a class="code" href="structPassenger_1_1PoolOptions.html#70251ed3cb3713cb26a0b166c6b015c0" title="The maximum number of requests that the spawned application may process before exiting...">maxRequests</a>;
559
+ <a name="l00543"></a>00543 domains[appRoot] = <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(domain);
560
+ <a name="l00544"></a>00544 } <span class="keywordflow">else</span> {
561
+ <a name="l00545"></a>00545 domain = it-&gt;second.get();
562
+ <a name="l00546"></a>00546 domain-&gt;size++;
563
+ <a name="l00547"></a>00547 }
564
+ <a name="l00548"></a>00548 instances = &amp;domain-&gt;instances;
565
+ <a name="l00549"></a>00549 instances-&gt;push_back(container);
566
+ <a name="l00550"></a>00550 container-&gt;iterator = instances-&gt;end();
567
+ <a name="l00551"></a>00551 container-&gt;iterator--;
568
+ <a name="l00552"></a>00552 count++;
569
+ <a name="l00553"></a>00553 active++;
570
+ <a name="l00554"></a>00554 activeOrMaxChanged.notify_all();
571
+ <a name="l00555"></a>00555 }
572
+ <a name="l00556"></a>00556 } <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) {
573
+ <a name="l00557"></a>00557 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
574
+ <a name="l00558"></a>00558 message.append(appRoot);
575
+ <a name="l00559"></a>00559 message.append(<span class="stringliteral">"': "</span>);
576
+ <a name="l00560"></a>00560 message.append(e.<a class="code" href="classPassenger_1_1SpawnException.html#d2da180f89a43423a4b37248249972ff">what</a>());
577
+ <a name="l00561"></a>00561 <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>()) {
578
+ <a name="l00562"></a>00562 <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>());
579
+ <a name="l00563"></a>00563 } <span class="keywordflow">else</span> {
580
+ <a name="l00564"></a>00564 <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);
581
+ <a name="l00565"></a>00565 }
582
+ <a name="l00566"></a>00566 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
583
+ <a name="l00567"></a>00567 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot spawn application '"</span>);
584
+ <a name="l00568"></a>00568 message.append(appRoot);
585
+ <a name="l00569"></a>00569 message.append(<span class="stringliteral">"': "</span>);
586
+ <a name="l00570"></a>00570 message.append(e.what());
587
+ <a name="l00571"></a>00571 <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);
588
+ <a name="l00572"></a>00572 }
589
+ <a name="l00573"></a>00573
590
+ <a name="l00574"></a>00574 <span class="keywordflow">return</span> make_pair(container, domain);
591
+ <a name="l00575"></a>00575 }
592
+ <a name="l00576"></a>00576
593
+ <a name="l00577"></a>00577 <span class="keyword">public</span>:<span class="comment"></span>
594
+ <a name="l00578"></a>00578 <span class="comment"> /**</span>
595
+ <a name="l00579"></a>00579 <span class="comment"> * Create a new StandardApplicationPool object.</span>
596
+ <a name="l00580"></a>00580 <span class="comment"> *</span>
597
+ <a name="l00581"></a>00581 <span class="comment"> * @param spawnServerCommand The filename of the spawn server to use.</span>
598
+ <a name="l00582"></a>00582 <span class="comment"> * @param logFile Specify a log file that the spawn server should use.</span>
599
+ <a name="l00583"></a>00583 <span class="comment"> * Messages on its standard output and standard error channels</span>
600
+ <a name="l00584"></a>00584 <span class="comment"> * will be written to this log file. If an empty string is</span>
601
+ <a name="l00585"></a>00585 <span class="comment"> * specified, no log file will be used, and the spawn server</span>
602
+ <a name="l00586"></a>00586 <span class="comment"> * will use the same standard output/error channels as the</span>
603
+ <a name="l00587"></a>00587 <span class="comment"> * current process.</span>
604
+ <a name="l00588"></a>00588 <span class="comment"> * @param rubyCommand The Ruby interpreter's command.</span>
605
+ <a name="l00589"></a>00589 <span class="comment"> * @param user The user that the spawn manager should run as. This</span>
606
+ <a name="l00590"></a>00590 <span class="comment"> * parameter only has effect if the current process is</span>
607
+ <a name="l00591"></a>00591 <span class="comment"> * running as root. If the empty string is given, or if</span>
608
+ <a name="l00592"></a>00592 <span class="comment"> * the &lt;tt&gt;user&lt;/tt&gt; is not a valid username, then</span>
609
+ <a name="l00593"></a>00593 <span class="comment"> * the spawn manager will be run as the current user.</span>
610
+ <a name="l00594"></a>00594 <span class="comment"> * @throws SystemException An error occured while trying to setup the spawn server.</span>
611
+ <a name="l00595"></a>00595 <span class="comment"> * @throws IOException The specified log file could not be opened.</span>
612
+ <a name="l00596"></a>00596 <span class="comment"> */</span>
613
+ <a name="l00597"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#f175704fc477f37ba1d387be09fa2e6b">00597</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,
614
+ <a name="l00598"></a>00598 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;logFile = <span class="stringliteral">""</span>,
615
+ <a name="l00599"></a>00599 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;rubyCommand = <span class="stringliteral">"ruby"</span>,
616
+ <a name="l00600"></a>00600 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;user = <span class="stringliteral">""</span>)
617
+ <a name="l00601"></a>00601 :
618
+ <a name="l00602"></a>00602 #ifndef PASSENGER_USE_DUMMY_SPAWN_MANAGER
619
+ <a name="l00603"></a>00603 spawnManager(spawnServerCommand, logFile, rubyCommand, user),
620
+ <a name="l00604"></a>00604 #endif
621
+ <a name="l00605"></a>00605 data(new SharedData()),
622
+ <a name="l00606"></a>00606 lock(data-&gt;lock),
623
+ <a name="l00607"></a>00607 activeOrMaxChanged(data-&gt;activeOrMaxChanged),
624
+ <a name="l00608"></a>00608 domains(data-&gt;domains),
625
+ <a name="l00609"></a>00609 max(data-&gt;max),
626
+ <a name="l00610"></a>00610 count(data-&gt;count),
627
+ <a name="l00611"></a>00611 active(data-&gt;active),
628
+ <a name="l00612"></a>00612 maxPerApp(data-&gt;maxPerApp),
629
+ <a name="l00613"></a>00613 inactiveApps(data-&gt;inactiveApps),
630
+ <a name="l00614"></a>00614 appInstanceCount(data-&gt;appInstanceCount)
631
+ <a name="l00615"></a>00615 {
632
+ <a name="l00616"></a>00616 TRACE_POINT();
633
+ <a name="l00617"></a>00617 detached = <span class="keyword">false</span>;
634
+ <a name="l00618"></a>00618 done = <span class="keyword">false</span>;
635
+ <a name="l00619"></a>00619 max = DEFAULT_MAX_POOL_SIZE;
636
+ <a name="l00620"></a>00620 count = 0;
637
+ <a name="l00621"></a>00621 active = 0;
638
+ <a name="l00622"></a>00622 waitingOnGlobalQueue = 0;
639
+ <a name="l00623"></a>00623 maxPerApp = DEFAULT_MAX_INSTANCES_PER_APP;
640
+ <a name="l00624"></a>00624 maxIdleTime = DEFAULT_MAX_IDLE_TIME;
641
+ <a name="l00625"></a>00625 cleanerThread = <span class="keyword">new</span> boost::thread(
642
+ <a name="l00626"></a>00626 bind(&amp;StandardApplicationPool::cleanerThreadMainLoop, <span class="keyword">this</span>),
643
+ <a name="l00627"></a>00627 CLEANER_THREAD_STACK_SIZE
644
+ <a name="l00628"></a>00628 );
645
+ <a name="l00629"></a>00629 }
646
+ <a name="l00630"></a>00630
647
+ <a name="l00631"></a>00631 <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>() {
648
+ <a name="l00632"></a>00632 <span class="keywordflow">if</span> (!detached) {
649
+ <a name="l00633"></a>00633 this_thread::disable_interruption di;
650
+ <a name="l00634"></a>00634 {
651
+ <a name="l00635"></a>00635 boost::mutex::scoped_lock l(lock);
652
+ <a name="l00636"></a>00636 done = <span class="keyword">true</span>;
653
+ <a name="l00637"></a>00637 cleanerThreadSleeper.notify_one();
654
+ <a name="l00638"></a>00638 }
655
+ <a name="l00639"></a>00639 cleanerThread-&gt;join();
656
+ <a name="l00640"></a>00640 }
657
+ <a name="l00641"></a>00641 <span class="keyword">delete</span> cleanerThread;
658
+ <a name="l00642"></a>00642 }
659
+ <a name="l00643"></a>00643
660
+ <a name="l00644"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#5a33f0766bbcfb2a48e08fc27bd1b684">00644</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>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appRoot) {
661
+ <a name="l00645"></a>00645 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#0b206eb4eb2869423d75c042a0653c67" title="Open a new session with the application specified by PoolOptions.appRoot.">ApplicationPool::get</a>(appRoot);
662
+ <a name="l00646"></a>00646 }
663
+ <a name="l00647"></a>00647
664
+ <a name="l00648"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#ffc8f3ef8b1d925d203794d191d7fef4">00648</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>(<span class="keyword">const</span> <a class="code" href="structPassenger_1_1PoolOptions.html" title="This struct encapsulates information for ApplicationPool::get() and for SpawnManager::spawn()...">PoolOptions</a> &amp;options) {
665
+ <a name="l00649"></a>00649 TRACE_POINT();
666
+ <a name="l00650"></a>00650 <span class="keyword">using namespace </span>boost::posix_time;
667
+ <a name="l00651"></a>00651 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> attempt = 0;
668
+ <a name="l00652"></a>00652 <span class="comment">// TODO: We should probably add a timeout to the following</span>
669
+ <a name="l00653"></a>00653 <span class="comment">// lock. This way we can fail gracefully if the server's under</span>
670
+ <a name="l00654"></a>00654 <span class="comment">// rediculous load. Though I'm not sure how much it really helps.</span>
671
+ <a name="l00655"></a>00655 unique_lock&lt;boost::mutex&gt; l(lock);
672
+ <a name="l00656"></a>00656
673
+ <a name="l00657"></a>00657 <span class="keywordflow">while</span> (<span class="keyword">true</span>) {
674
+ <a name="l00658"></a>00658 attempt++;
675
+ <a name="l00659"></a>00659
676
+ <a name="l00660"></a>00660 pair&lt;AppContainerPtr, Domain *&gt; p(
677
+ <a name="l00661"></a>00661 spawnOrUseExisting(l, options)
678
+ <a name="l00662"></a>00662 );
679
+ <a name="l00663"></a>00663 AppContainerPtr &amp;container = p.first;
680
+ <a name="l00664"></a>00664 Domain *domain = p.second;
681
+ <a name="l00665"></a>00665
682
+ <a name="l00666"></a>00666 container-&gt;lastUsed = time(NULL);
683
+ <a name="l00667"></a>00667 container-&gt;sessions++;
684
+ <a name="l00668"></a>00668
685
+ <a name="l00669"></a>00669 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
686
+ <a name="l00670"></a>00670 <span class="stringliteral">"State is valid:\n"</span> &lt;&lt; <a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383" title="Returns a textual description of the internal state of the application pool.">toString</a>(<span class="keyword">false</span>));
687
+ <a name="l00671"></a>00671 <span class="keywordflow">try</span> {
688
+ <a name="l00672"></a>00672 UPDATE_TRACE_POINT();
689
+ <a name="l00673"></a>00673 <span class="keywordflow">return</span> container-&gt;app-&gt;connect(SessionCloseCallback(data, container));
690
+ <a name="l00674"></a>00674 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> exception &amp;e) {
691
+ <a name="l00675"></a>00675 container-&gt;sessions--;
692
+ <a name="l00676"></a>00676
693
+ <a name="l00677"></a>00677 AppContainerList &amp;instances(domain-&gt;instances);
694
+ <a name="l00678"></a>00678 instances.erase(container-&gt;iterator);
695
+ <a name="l00679"></a>00679 domain-&gt;size--;
696
+ <a name="l00680"></a>00680 <span class="keywordflow">if</span> (instances.empty()) {
697
+ <a name="l00681"></a>00681 domains.erase(options.<a class="code" href="structPassenger_1_1PoolOptions.html#822039d204b48d9ed49184646734acf3" title="The root directory of the application to spawn.">appRoot</a>);
698
+ <a name="l00682"></a>00682 }
699
+ <a name="l00683"></a>00683 count--;
700
+ <a name="l00684"></a>00684 active--;
701
+ <a name="l00685"></a>00685 activeOrMaxChanged.notify_all();
702
+ <a name="l00686"></a>00686 P_ASSERT(verifyState(), <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>(),
703
+ <a name="l00687"></a>00687 <span class="stringliteral">"State is valid: "</span> &lt;&lt; <a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383" title="Returns a textual description of the internal state of the application pool.">toString</a>(<span class="keyword">false</span>));
704
+ <a name="l00688"></a>00688 <span class="keywordflow">if</span> (attempt == MAX_GET_ATTEMPTS) {
705
+ <a name="l00689"></a>00689 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot connect to an existing "</span>
706
+ <a name="l00690"></a>00690 <span class="stringliteral">"application instance for '"</span>);
707
+ <a name="l00691"></a>00691 message.append(options.<a class="code" href="structPassenger_1_1PoolOptions.html#822039d204b48d9ed49184646734acf3" title="The root directory of the application to spawn.">appRoot</a>);
708
+ <a name="l00692"></a>00692 message.append(<span class="stringliteral">"': "</span>);
709
+ <a name="l00693"></a>00693 <span class="keywordflow">try</span> {
710
+ <a name="l00694"></a>00694 <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 =
711
+ <a name="l00695"></a>00695 <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);
712
+ <a name="l00696"></a>00696 message.append(syse.<a class="code" href="classPassenger_1_1SystemException.html#0ef41d755fea2c9b1db2252e7c418dc8" title="Returns the system&amp;#39;s error message.">sys</a>());
713
+ <a name="l00697"></a>00697 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> bad_cast &amp;) {
714
+ <a name="l00698"></a>00698 message.append(e.what());
715
+ <a name="l00699"></a>00699 }
716
+ <a name="l00700"></a>00700 <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);
717
+ <a name="l00701"></a>00701 }
718
+ <a name="l00702"></a>00702 }
719
+ <a name="l00703"></a>00703 }
720
+ <a name="l00704"></a>00704 <span class="comment">// Never reached; shut up compiler warning</span>
721
+ <a name="l00705"></a>00705 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">Application::SessionPtr</a>();
722
+ <a name="l00706"></a>00706 }
723
+ <a name="l00707"></a>00707
724
+ <a name="l00708"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#bcf8faeb4f431ae07ea0e20270661d08">00708</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>() {
725
+ <a name="l00709"></a>00709 boost::mutex::scoped_lock l(lock);
726
+ <a name="l00710"></a>00710 domains.clear();
727
+ <a name="l00711"></a>00711 inactiveApps.clear();
728
+ <a name="l00712"></a>00712 appInstanceCount.clear();
729
+ <a name="l00713"></a>00713 count = 0;
730
+ <a name="l00714"></a>00714 active = 0;
731
+ <a name="l00715"></a>00715 activeOrMaxChanged.notify_all();
732
+ <a name="l00716"></a>00716 }
733
+ <a name="l00717"></a>00717
734
+ <a name="l00718"></a>00718 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) {
735
+ <a name="l00719"></a>00719 boost::mutex::scoped_lock l(lock);
736
+ <a name="l00720"></a>00720 maxIdleTime = seconds;
737
+ <a name="l00721"></a>00721 cleanerThreadSleeper.notify_one();
738
+ <a name="l00722"></a>00722 }
739
+ <a name="l00723"></a>00723
740
+ <a name="l00724"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#04ef8c92da189520ad2022f4f82e9553">00724</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) {
741
+ <a name="l00725"></a>00725 boost::mutex::scoped_lock l(lock);
742
+ <a name="l00726"></a>00726 this-&gt;max = max;
743
+ <a name="l00727"></a>00727 activeOrMaxChanged.notify_all();
744
+ <a name="l00728"></a>00728 }
745
+ <a name="l00729"></a>00729
746
+ <a name="l00730"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#7773c4a3dfbd88eac72401d063831788">00730</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>{
747
+ <a name="l00731"></a>00731 <span class="keywordflow">return</span> active;
748
+ <a name="l00732"></a>00732 }
749
+ <a name="l00733"></a>00733
750
+ <a name="l00734"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#cdbfe2b9ffacdab4438c879c2411bf02">00734</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>{
751
+ <a name="l00735"></a>00735 <span class="keywordflow">return</span> count;
752
+ <a name="l00736"></a>00736 }
753
+ <a name="l00737"></a>00737
754
+ <a name="l00738"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#3bafcda8d880f70561ad8a9da16e26ef">00738</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) {
755
+ <a name="l00739"></a>00739 boost::mutex::scoped_lock l(lock);
756
+ <a name="l00740"></a>00740 this-&gt;maxPerApp = maxPerApp;
757
+ <a name="l00741"></a>00741 activeOrMaxChanged.notify_all();
758
+ <a name="l00742"></a>00742 }
759
+ <a name="l00743"></a>00743
760
+ <a name="l00744"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#6955152d237920988d20297d2fff5660">00744</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>{
761
+ <a name="l00745"></a>00745 <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>();
762
+ <a name="l00746"></a>00746 }
763
+ <a name="l00747"></a>00747 <span class="comment"></span>
764
+ <a name="l00748"></a>00748 <span class="comment"> /**</span>
765
+ <a name="l00749"></a>00749 <span class="comment"> * Returns a textual description of the internal state of</span>
766
+ <a name="l00750"></a>00750 <span class="comment"> * the application pool.</span>
767
+ <a name="l00751"></a>00751 <span class="comment"> */</span>
768
+ <a name="l00752"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383">00752</a> <span class="keyword">virtual</span> <span class="keywordtype">string</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#22b4149ca8256c3042fc342e681b0383" title="Returns a textual description of the internal state of the application pool.">toString</a>(<span class="keywordtype">bool</span> lockMutex = <span class="keyword">true</span>)<span class="keyword"> const </span>{
769
+ <a name="l00753"></a>00753 <span class="keywordflow">if</span> (lockMutex) {
770
+ <a name="l00754"></a>00754 unique_lock&lt;boost::mutex&gt; l(lock);
771
+ <a name="l00755"></a>00755 <span class="keywordflow">return</span> toStringWithoutLock();
772
+ <a name="l00756"></a>00756 } <span class="keywordflow">else</span> {
773
+ <a name="l00757"></a>00757 <span class="keywordflow">return</span> toStringWithoutLock();
774
+ <a name="l00758"></a>00758 }
775
+ <a name="l00759"></a>00759 }
776
+ <a name="l00760"></a>00760 <span class="comment"></span>
777
+ <a name="l00761"></a>00761 <span class="comment"> /**</span>
778
+ <a name="l00762"></a>00762 <span class="comment"> * Returns an XML description of the internal state of the</span>
779
+ <a name="l00763"></a>00763 <span class="comment"> * application pool.</span>
780
+ <a name="l00764"></a>00764 <span class="comment"> */</span>
781
+ <a name="l00765"></a><a class="code" href="classPassenger_1_1StandardApplicationPool.html#d153c41a1d0aca91d17cf36ed6fdda19">00765</a> <span class="keyword">virtual</span> <span class="keywordtype">string</span> <a class="code" href="classPassenger_1_1StandardApplicationPool.html#d153c41a1d0aca91d17cf36ed6fdda19" title="Returns an XML description of the internal state of the application pool.">toXml</a>()<span class="keyword"> const </span>{
782
+ <a name="l00766"></a>00766 unique_lock&lt;boost::mutex&gt; l(lock);
783
+ <a name="l00767"></a>00767 stringstream result;
784
+ <a name="l00768"></a>00768 DomainMap::const_iterator it;
785
+ <a name="l00769"></a>00769
786
+ <a name="l00770"></a>00770 result &lt;&lt; <span class="stringliteral">"&lt;?xml version=\"1.0\" encoding=\"iso8859-1\" ?&gt;\n"</span>;
787
+ <a name="l00771"></a>00771 result &lt;&lt; <span class="stringliteral">"&lt;info&gt;"</span>;
788
+ <a name="l00772"></a>00772
789
+ <a name="l00773"></a>00773 result &lt;&lt; <span class="stringliteral">"&lt;domains&gt;"</span>;
790
+ <a name="l00774"></a>00774 <span class="keywordflow">for</span> (it = domains.begin(); it != domains.end(); it++) {
791
+ <a name="l00775"></a>00775 Domain *domain = it-&gt;second.get();
792
+ <a name="l00776"></a>00776 AppContainerList *instances = &amp;domain-&gt;instances;
793
+ <a name="l00777"></a>00777 AppContainerList::const_iterator lit;
794
+ <a name="l00778"></a>00778
795
+ <a name="l00779"></a>00779 result &lt;&lt; <span class="stringliteral">"&lt;domain&gt;"</span>;
796
+ <a name="l00780"></a>00780 result &lt;&lt; <span class="stringliteral">"&lt;name&gt;"</span> &lt;&lt; <a class="code" href="group__Support.html#ge74addedf73782a1eb1f6dd48d6fce06" title="Escape the given raw string into an XML value.">escapeForXml</a>(it-&gt;first) &lt;&lt; <span class="stringliteral">"&lt;/name&gt;"</span>;
797
+ <a name="l00781"></a>00781
798
+ <a name="l00782"></a>00782 result &lt;&lt; <span class="stringliteral">"&lt;instances&gt;"</span>;
799
+ <a name="l00783"></a>00783 <span class="keywordflow">for</span> (lit = instances-&gt;begin(); lit != instances-&gt;end(); lit++) {
800
+ <a name="l00784"></a>00784 AppContainer *container = lit-&gt;get();
801
+ <a name="l00785"></a>00785
802
+ <a name="l00786"></a>00786 result &lt;&lt; <span class="stringliteral">"&lt;instance&gt;"</span>;
803
+ <a name="l00787"></a>00787 result &lt;&lt; <span class="stringliteral">"&lt;pid&gt;"</span> &lt;&lt; container-&gt;app-&gt;getPid() &lt;&lt; <span class="stringliteral">"&lt;/pid&gt;"</span>;
804
+ <a name="l00788"></a>00788 result &lt;&lt; <span class="stringliteral">"&lt;sessions&gt;"</span> &lt;&lt; container-&gt;sessions &lt;&lt; <span class="stringliteral">"&lt;/sessions&gt;"</span>;
805
+ <a name="l00789"></a>00789 result &lt;&lt; <span class="stringliteral">"&lt;processed&gt;"</span> &lt;&lt; container-&gt;processed &lt;&lt; <span class="stringliteral">"&lt;/processed&gt;"</span>;
806
+ <a name="l00790"></a>00790 result &lt;&lt; <span class="stringliteral">"&lt;uptime&gt;"</span> &lt;&lt; container-&gt;uptime() &lt;&lt; <span class="stringliteral">"&lt;/uptime&gt;"</span>;
807
+ <a name="l00791"></a>00791 result &lt;&lt; <span class="stringliteral">"&lt;/instance&gt;"</span>;
808
+ <a name="l00792"></a>00792 }
809
+ <a name="l00793"></a>00793 result &lt;&lt; <span class="stringliteral">"&lt;/instances&gt;"</span>;
810
+ <a name="l00794"></a>00794
811
+ <a name="l00795"></a>00795 result &lt;&lt; <span class="stringliteral">"&lt;/domain&gt;"</span>;
812
+ <a name="l00796"></a>00796 }
813
+ <a name="l00797"></a>00797 result &lt;&lt; <span class="stringliteral">"&lt;/domains&gt;"</span>;
814
+ <a name="l00798"></a>00798
815
+ <a name="l00799"></a>00799 result &lt;&lt; <span class="stringliteral">"&lt;/info&gt;"</span>;
816
+ <a name="l00800"></a>00800 <span class="keywordflow">return</span> result.str();
817
+ <a name="l00801"></a>00801 }
818
+ <a name="l00802"></a>00802 };
819
+ <a name="l00803"></a>00803
820
+ <a name="l00804"></a>00804 <span class="keyword">typedef</span> shared_ptr&lt;StandardApplicationPool&gt; StandardApplicationPoolPtr;
821
+ <a name="l00805"></a>00805
822
+ <a name="l00806"></a>00806 } <span class="comment">// namespace Passenger</span>
823
+ <a name="l00807"></a>00807
824
+ <a name="l00808"></a>00808 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_STANDARD_APPLICATION_POOL_H_ */</span>
825
+ <a name="l00809"></a>00809
726
826
  </pre></div></div>
727
- <hr size="1"><address style="text-align: right;"><small>Generated on Mon Dec 15 15:27:24 2008 for Passenger by&nbsp;
827
+ <hr size="1"><address style="text-align: right;"><small>Generated on Fri Mar 13 19:24:32 2009 for Passenger by&nbsp;
728
828
  <a href="http://www.doxygen.org/index.html">
729
829
  <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
730
830
  </body>