passenger 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (275) hide show
  1. data/Rakefile +8 -5
  2. data/bin/passenger-install-apache2-module +6 -1
  3. data/doc/ApplicationPool algorithm.txt +23 -5
  4. data/doc/Architectural overview.html +778 -0
  5. data/doc/Security of user switching support.html +1 -1
  6. data/doc/Users guide.html +113 -31
  7. data/doc/Users guide.txt +104 -10
  8. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +683 -0
  9. data/doc/cxxapi/ApplicationPool_8h-source.html +224 -0
  10. data/doc/cxxapi/Application_8h-source.html +448 -0
  11. data/doc/cxxapi/Bucket_8h-source.html +61 -0
  12. data/doc/cxxapi/Configuration_8h-source.html +195 -0
  13. data/doc/cxxapi/DummySpawnManager_8h-source.html +126 -0
  14. data/doc/cxxapi/Exceptions_8h-source.html +244 -0
  15. data/doc/cxxapi/Hooks_8h-source.html +63 -0
  16. data/doc/cxxapi/Logging_8h-source.html +136 -0
  17. data/doc/cxxapi/MessageChannel_8h-source.html +524 -0
  18. data/doc/cxxapi/SpawnManager_8h-source.html +593 -0
  19. data/doc/cxxapi/StandardApplicationPool_8h-source.html +732 -0
  20. data/doc/cxxapi/System_8h-source.html +251 -0
  21. data/doc/cxxapi/Utils_8h-source.html +283 -0
  22. data/doc/cxxapi/annotated.html +59 -0
  23. data/doc/cxxapi/classClient-members.html +35 -0
  24. data/doc/cxxapi/classClient.html +117 -0
  25. data/doc/cxxapi/classDirectoryMapper-members.html +38 -0
  26. data/doc/cxxapi/classDirectoryMapper.html +203 -0
  27. data/doc/cxxapi/classHooks-members.html +33 -0
  28. data/doc/cxxapi/classHooks.html +43 -0
  29. data/doc/cxxapi/classPassenger_1_1Application-members.html +38 -0
  30. data/doc/cxxapi/classPassenger_1_1Application.html +229 -0
  31. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +41 -0
  32. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +359 -0
  33. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +36 -0
  34. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +225 -0
  35. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -0
  36. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -0
  37. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  38. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +43 -0
  39. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +329 -0
  40. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +33 -0
  41. data/doc/cxxapi/classPassenger_1_1BusyException.html +47 -0
  42. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +33 -0
  43. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +44 -0
  44. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +33 -0
  45. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +51 -0
  46. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +33 -0
  47. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +51 -0
  48. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -0
  49. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -0
  50. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +38 -0
  52. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +61 -0
  53. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -0
  54. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -0
  55. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  56. data/doc/cxxapi/classPassenger_1_1IOException-members.html +33 -0
  57. data/doc/cxxapi/classPassenger_1_1IOException.html +54 -0
  58. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -0
  59. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -0
  60. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  61. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +47 -0
  62. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +591 -0
  63. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +35 -0
  64. data/doc/cxxapi/classPassenger_1_1SpawnException.html +77 -0
  65. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +37 -0
  66. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +255 -0
  67. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +43 -0
  68. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +400 -0
  69. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -0
  70. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -0
  71. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  72. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +37 -0
  73. data/doc/cxxapi/classPassenger_1_1SystemException.html +154 -0
  74. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -0
  75. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -0
  76. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  77. data/doc/cxxapi/classPassenger_1_1TempFile-members.html +36 -0
  78. data/doc/cxxapi/classPassenger_1_1TempFile.html +128 -0
  79. data/doc/cxxapi/classPassenger_1_1Thread-members.html +35 -0
  80. data/doc/cxxapi/classPassenger_1_1Thread.html +100 -0
  81. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption-members.html +33 -0
  82. data/doc/cxxapi/classboost_1_1this__thread_1_1disable__syscall__interruption.html +46 -0
  83. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption-members.html +33 -0
  84. data/doc/cxxapi/classboost_1_1this__thread_1_1enable__syscall__interruption.html +44 -0
  85. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption-members.html +33 -0
  86. data/doc/cxxapi/classboost_1_1this__thread_1_1restore__syscall__interruption.html +44 -0
  87. data/doc/cxxapi/definitions_8h-source.html +28 -0
  88. data/doc/cxxapi/doxygen.css +433 -0
  89. data/doc/cxxapi/doxygen.png +0 -0
  90. data/doc/cxxapi/files.html +42 -0
  91. data/doc/cxxapi/ftv2blank.png +0 -0
  92. data/doc/cxxapi/ftv2doc.png +0 -0
  93. data/doc/cxxapi/ftv2folderclosed.png +0 -0
  94. data/doc/cxxapi/ftv2folderopen.png +0 -0
  95. data/doc/cxxapi/ftv2lastnode.png +0 -0
  96. data/doc/cxxapi/ftv2link.png +0 -0
  97. data/doc/cxxapi/ftv2mlastnode.png +0 -0
  98. data/doc/cxxapi/ftv2mnode.png +0 -0
  99. data/doc/cxxapi/ftv2node.png +0 -0
  100. data/doc/cxxapi/ftv2plastnode.png +0 -0
  101. data/doc/cxxapi/ftv2pnode.png +0 -0
  102. data/doc/cxxapi/ftv2vertline.png +0 -0
  103. data/doc/cxxapi/functions.html +215 -0
  104. data/doc/cxxapi/functions_func.html +210 -0
  105. data/doc/cxxapi/functions_type.html +46 -0
  106. data/doc/cxxapi/functions_vars.html +48 -0
  107. data/doc/cxxapi/graph_legend.dot +22 -0
  108. data/doc/cxxapi/graph_legend.html +87 -0
  109. data/doc/cxxapi/graph_legend.png +0 -0
  110. data/doc/cxxapi/group__Configuration.html +236 -0
  111. data/doc/cxxapi/group__Configuration.png +0 -0
  112. data/doc/cxxapi/group__Core.html +51 -0
  113. data/doc/cxxapi/group__Core.png +0 -0
  114. data/doc/cxxapi/group__Exceptions.html +43 -0
  115. data/doc/cxxapi/group__Hooks.html +46 -0
  116. data/doc/cxxapi/group__Hooks.png +0 -0
  117. data/doc/cxxapi/group__Support.html +406 -0
  118. data/doc/cxxapi/hierarchy.html +67 -0
  119. data/doc/cxxapi/index.html +11 -0
  120. data/doc/cxxapi/inherit__graph__0.map +1 -0
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -0
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -0
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -0
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -0
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -0
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -0
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -0
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -0
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -0
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -0
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -0
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -0
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -0
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -0
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -0
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -0
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -0
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -0
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -0
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -0
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -0
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +2 -0
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -0
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -0
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -0
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +1 -0
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -0
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -0
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -0
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -0
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -0
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -0
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -0
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -0
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -0
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +1 -0
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -0
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -0
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -0
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -0
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -0
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +2 -0
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -0
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +102 -0
  187. data/doc/cxxapi/main.html +27 -0
  188. data/doc/cxxapi/modules.html +34 -0
  189. data/doc/cxxapi/namespacePassenger.html +208 -0
  190. data/doc/cxxapi/namespacePassenger_1_1InterruptableCalls.html +43 -0
  191. data/doc/cxxapi/namespacemembers.html +70 -0
  192. data/doc/cxxapi/namespacemembers_func.html +66 -0
  193. data/doc/cxxapi/namespacemembers_type.html +46 -0
  194. data/doc/cxxapi/namespaces.html +35 -0
  195. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +33 -0
  196. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +49 -0
  197. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +33 -0
  198. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +49 -0
  199. data/doc/cxxapi/tab_b.gif +0 -0
  200. data/doc/cxxapi/tab_l.gif +0 -0
  201. data/doc/cxxapi/tab_r.gif +0 -0
  202. data/doc/cxxapi/tabs.css +102 -0
  203. data/doc/cxxapi/tree.html +167 -0
  204. data/doc/rdoc/classes/ConditionVariable.html +160 -0
  205. data/doc/rdoc/classes/Exception.html +120 -0
  206. data/doc/rdoc/classes/GC.html +113 -0
  207. data/doc/rdoc/classes/IO.html +150 -0
  208. data/doc/rdoc/classes/Passenger.html +136 -0
  209. data/doc/rdoc/classes/Passenger/AbstractRequestHandler.html +402 -0
  210. data/doc/rdoc/classes/Passenger/AbstractServer.html +649 -0
  211. data/doc/rdoc/classes/Passenger/AbstractServer/ServerAlreadyStarted.html +97 -0
  212. data/doc/rdoc/classes/Passenger/AbstractServer/ServerError.html +96 -0
  213. data/doc/rdoc/classes/Passenger/AbstractServer/ServerNotStarted.html +97 -0
  214. data/doc/rdoc/classes/Passenger/AbstractServer/UnknownMessage.html +96 -0
  215. data/doc/rdoc/classes/Passenger/AppInitError.html +137 -0
  216. data/doc/rdoc/classes/Passenger/Application.html +298 -0
  217. data/doc/rdoc/classes/Passenger/ConsoleTextTemplate.html +172 -0
  218. data/doc/rdoc/classes/Passenger/FrameworkInitError.html +143 -0
  219. data/doc/rdoc/classes/Passenger/HTMLTemplate.html +175 -0
  220. data/doc/rdoc/classes/Passenger/InitializationError.html +141 -0
  221. data/doc/rdoc/classes/Passenger/MessageChannel.html +488 -0
  222. data/doc/rdoc/classes/Passenger/NativeSupport.html +320 -0
  223. data/doc/rdoc/classes/Passenger/SpawnManager.html +375 -0
  224. data/doc/rdoc/classes/Passenger/UnknownError.html +125 -0
  225. data/doc/rdoc/classes/Passenger/Utils.html +578 -0
  226. data/doc/rdoc/classes/Passenger/VersionNotFound.html +140 -0
  227. data/doc/rdoc/classes/PlatformInfo.html +302 -0
  228. data/doc/rdoc/classes/RakeExtensions.html +197 -0
  229. data/doc/rdoc/created.rid +1 -0
  230. data/doc/rdoc/files/DEVELOPERS_TXT.html +230 -0
  231. data/doc/rdoc/files/README.html +150 -0
  232. data/doc/rdoc/files/ext/passenger/native_support_c.html +92 -0
  233. data/doc/rdoc/files/lib/passenger/abstract_request_handler_rb.html +126 -0
  234. data/doc/rdoc/files/lib/passenger/abstract_server_rb.html +127 -0
  235. data/doc/rdoc/files/lib/passenger/application_rb.html +123 -0
  236. data/doc/rdoc/files/lib/passenger/console_text_template_rb.html +122 -0
  237. data/doc/rdoc/files/lib/passenger/constants_rb.html +114 -0
  238. data/doc/rdoc/files/lib/passenger/dependencies_rb.html +130 -0
  239. data/doc/rdoc/files/lib/passenger/exceptions_rb.html +118 -0
  240. data/doc/rdoc/files/lib/passenger/html_template_rb.html +122 -0
  241. data/doc/rdoc/files/lib/passenger/message_channel_rb.html +118 -0
  242. data/doc/rdoc/files/lib/passenger/platform_info_rb.html +122 -0
  243. data/doc/rdoc/files/lib/passenger/simple_benchmarking_rb.html +118 -0
  244. data/doc/rdoc/files/lib/passenger/spawn_manager_rb.html +139 -0
  245. data/doc/rdoc/files/lib/passenger/utils_rb.html +130 -0
  246. data/doc/rdoc/files/lib/rake/extensions_rb.html +122 -0
  247. data/doc/rdoc/fr_class_index.html +71 -0
  248. data/doc/rdoc/fr_file_index.html +63 -0
  249. data/doc/rdoc/fr_method_index.html +120 -0
  250. data/doc/rdoc/index.html +26 -0
  251. data/doc/rdoc/rdoc-style.css +187 -0
  252. data/ext/apache2/ApplicationPool.h +12 -0
  253. data/ext/apache2/ApplicationPoolServer.h +6 -0
  254. data/ext/apache2/ApplicationPoolServerExecutable.cpp +6 -0
  255. data/ext/apache2/Bucket.cpp +63 -69
  256. data/ext/apache2/Bucket.h +2 -0
  257. data/ext/apache2/Configuration.cpp +24 -0
  258. data/ext/apache2/Configuration.h +16 -1
  259. data/ext/apache2/Hooks.cpp +5 -3
  260. data/ext/apache2/StandardApplicationPool.h +30 -11
  261. data/lib/passenger/abstract_request_handler.rb +3 -0
  262. data/lib/passenger/abstract_server.rb +3 -3
  263. data/lib/passenger/application.rb +4 -2
  264. data/lib/passenger/dependencies.rb +10 -1
  265. data/lib/passenger/platform_info.rb +40 -1
  266. data/lib/passenger/rack/request_handler.rb +4 -2
  267. data/lib/passenger/railz/application_spawner.rb +7 -1
  268. data/lib/passenger/utils.rb +6 -8
  269. data/lib/rake/gempackagetask.rb +0 -6
  270. data/lib/rake/rdoctask.rb +84 -23
  271. data/test/ApplicationPoolTest.cpp +36 -0
  272. data/test/ruby/rails/minimal_spawner_spec.rb +8 -0
  273. data/test/ruby/utils_spec.rb +33 -0
  274. data/test/stub/rails_apps/foobar/config/environments/production.rb +0 -1
  275. metadata +262 -5
@@ -0,0 +1,224 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
3
+ <title>Passenger: ApplicationPool.h Source File</title>
4
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
5
+ <link href="tabs.css" rel="stylesheet" type="text/css">
6
+ </head><body>
7
+ <!-- Generated by Doxygen 1.5.5 -->
8
+ <div class="navigation" id="top">
9
+ <div class="tabs">
10
+ <ul>
11
+ <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
12
+ <li><a href="modules.html"><span>Modules</span></a></li>
13
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
14
+ <li><a href="annotated.html"><span>Classes</span></a></li>
15
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
16
+ </ul>
17
+ </div>
18
+ <h1>ApplicationPool.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
19
+ <a name="l00002"></a>00002 <span class="comment"> * Phusion Passenger - http://www.modrails.com/</span>
20
+ <a name="l00003"></a>00003 <span class="comment"> * Copyright (C) 2008 Phusion</span>
21
+ <a name="l00004"></a>00004 <span class="comment"> *</span>
22
+ <a name="l00005"></a>00005 <span class="comment"> * Phusion Passenger is a trademark of Hongli Lai &amp; Ninh Bui.</span>
23
+ <a name="l00006"></a>00006 <span class="comment"> *</span>
24
+ <a name="l00007"></a>00007 <span class="comment"> * This program is free software; you can redistribute it and/or modify</span>
25
+ <a name="l00008"></a>00008 <span class="comment"> * it under the terms of the GNU General Public License as published by</span>
26
+ <a name="l00009"></a>00009 <span class="comment"> * the Free Software Foundation; version 2 of the License.</span>
27
+ <a name="l00010"></a>00010 <span class="comment"> *</span>
28
+ <a name="l00011"></a>00011 <span class="comment"> * This program is distributed in the hope that it will be useful,</span>
29
+ <a name="l00012"></a>00012 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
30
+ <a name="l00013"></a>00013 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
31
+ <a name="l00014"></a>00014 <span class="comment"> * GNU General Public License for more details.</span>
32
+ <a name="l00015"></a>00015 <span class="comment"> *</span>
33
+ <a name="l00016"></a>00016 <span class="comment"> * You should have received a copy of the GNU General Public License along</span>
34
+ <a name="l00017"></a>00017 <span class="comment"> * with this program; if not, write to the Free Software Foundation, Inc.,</span>
35
+ <a name="l00018"></a>00018 <span class="comment"> * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span>
36
+ <a name="l00019"></a>00019 <span class="comment"> */</span>
37
+ <a name="l00020"></a>00020 <span class="preprocessor">#ifndef _PASSENGER_APPLICATION_POOL_H_</span>
38
+ <a name="l00021"></a>00021 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_APPLICATION_POOL_H_</span>
39
+ <a name="l00022"></a>00022 <span class="preprocessor"></span>
40
+ <a name="l00023"></a>00023 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
41
+ <a name="l00024"></a>00024 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
42
+ <a name="l00025"></a>00025
43
+ <a name="l00026"></a>00026 <span class="preprocessor">#include "Application.h"</span>
44
+ <a name="l00027"></a>00027
45
+ <a name="l00028"></a>00028 <span class="keyword">namespace </span>Passenger {
46
+ <a name="l00029"></a>00029
47
+ <a name="l00030"></a>00030 <span class="keyword">using namespace </span>std;
48
+ <a name="l00031"></a>00031 <span class="keyword">using namespace </span>boost;
49
+ <a name="l00032"></a>00032 <span class="comment"></span>
50
+ <a name="l00033"></a>00033 <span class="comment">/**</span>
51
+ <a name="l00034"></a>00034 <span class="comment"> * A persistent pool of Applications.</span>
52
+ <a name="l00035"></a>00035 <span class="comment"> *</span>
53
+ <a name="l00036"></a>00036 <span class="comment"> * Spawning application instances, especially Ruby on Rails ones, is a very expensive operation.</span>
54
+ <a name="l00037"></a>00037 <span class="comment"> * Despite best efforts to make the operation less expensive (see SpawnManager),</span>
55
+ <a name="l00038"></a>00038 <span class="comment"> * it remains expensive compared to the cost of processing an HTTP request/response.</span>
56
+ <a name="l00039"></a>00039 <span class="comment"> * So, in order to solve this, some sort of caching/pooling mechanism will be required.</span>
57
+ <a name="l00040"></a>00040 <span class="comment"> * ApplicationPool provides this.</span>
58
+ <a name="l00041"></a>00041 <span class="comment"> *</span>
59
+ <a name="l00042"></a>00042 <span class="comment"> * Normally, one would use SpawnManager to spawn a new RoR/Rack application instance,</span>
60
+ <a name="l00043"></a>00043 <span class="comment"> * then use Application::connect() to create a new session with that application</span>
61
+ <a name="l00044"></a>00044 <span class="comment"> * instance, and then use the returned Session object to send the request and</span>
62
+ <a name="l00045"></a>00045 <span class="comment"> * to read the HTTP response. ApplicationPool replaces the first step with</span>
63
+ <a name="l00046"></a>00046 <span class="comment"> * a call to Application::get(). For example:</span>
64
+ <a name="l00047"></a>00047 <span class="comment"> * @code</span>
65
+ <a name="l00048"></a>00048 <span class="comment"> * ApplicationPool pool = some_function_which_creates_an_application_pool();</span>
66
+ <a name="l00049"></a>00049 <span class="comment"> * </span>
67
+ <a name="l00050"></a>00050 <span class="comment"> * // Connect to the application and get the newly opened session.</span>
68
+ <a name="l00051"></a>00051 <span class="comment"> * Application::SessionPtr session(pool-&gt;get("/home/webapps/foo"));</span>
69
+ <a name="l00052"></a>00052 <span class="comment"> * </span>
70
+ <a name="l00053"></a>00053 <span class="comment"> * // Send the request headers and request body data.</span>
71
+ <a name="l00054"></a>00054 <span class="comment"> * session-&gt;sendHeaders(...);</span>
72
+ <a name="l00055"></a>00055 <span class="comment"> * session-&gt;sendBodyBlock(...);</span>
73
+ <a name="l00056"></a>00056 <span class="comment"> * // Done sending data, so we shutdown the writer stream.</span>
74
+ <a name="l00057"></a>00057 <span class="comment"> * session-&gt;shutdownWriter();</span>
75
+ <a name="l00058"></a>00058 <span class="comment"> *</span>
76
+ <a name="l00059"></a>00059 <span class="comment"> * // Now read the HTTP response.</span>
77
+ <a name="l00060"></a>00060 <span class="comment"> * string responseData = readAllDataFromSocket(session-&gt;getStream());</span>
78
+ <a name="l00061"></a>00061 <span class="comment"> * // Done reading data, so we shutdown the reader stream.</span>
79
+ <a name="l00062"></a>00062 <span class="comment"> * session-&gt;shutdownReader();</span>
80
+ <a name="l00063"></a>00063 <span class="comment"> *</span>
81
+ <a name="l00064"></a>00064 <span class="comment"> * // This session has now finished, so we close the session by resetting</span>
82
+ <a name="l00065"></a>00065 <span class="comment"> * // the smart pointer to NULL (thereby destroying the Session object).</span>
83
+ <a name="l00066"></a>00066 <span class="comment"> * session.reset();</span>
84
+ <a name="l00067"></a>00067 <span class="comment"> *</span>
85
+ <a name="l00068"></a>00068 <span class="comment"> * // We can connect to an Application multiple times. Just make sure</span>
86
+ <a name="l00069"></a>00069 <span class="comment"> * // the previous session is closed.</span>
87
+ <a name="l00070"></a>00070 <span class="comment"> * session = app-&gt;connect("/home/webapps/bar")</span>
88
+ <a name="l00071"></a>00071 <span class="comment"> * @endcode</span>
89
+ <a name="l00072"></a>00072 <span class="comment"> *</span>
90
+ <a name="l00073"></a>00073 <span class="comment"> * Internally, ApplicationPool::get() will keep spawned applications instances in</span>
91
+ <a name="l00074"></a>00074 <span class="comment"> * memory, and reuse them if possible. It wil* @throw l try to keep spawning to a minimum.</span>
92
+ <a name="l00075"></a>00075 <span class="comment"> * Furthermore, if an application instance hasn't been used for a while, it</span>
93
+ <a name="l00076"></a>00076 <span class="comment"> * will be automatically shutdown in order to save memory. Restart requests are</span>
94
+ <a name="l00077"></a>00077 <span class="comment"> * honored: if an application has the file 'restart.txt' in its 'tmp' folder,</span>
95
+ <a name="l00078"></a>00078 <span class="comment"> * then get() will shutdown existing instances of that application and spawn</span>
96
+ <a name="l00079"></a>00079 <span class="comment"> * a new instance (this is useful when a new version of an application has been</span>
97
+ <a name="l00080"></a>00080 <span class="comment"> * deployed). And finally, one can set a hard limit on the maximum number of</span>
98
+ <a name="l00081"></a>00081 <span class="comment"> * applications instances that may be spawned (see ApplicationPool::setMax()).</span>
99
+ <a name="l00082"></a>00082 <span class="comment"> *</span>
100
+ <a name="l00083"></a>00083 <span class="comment"> * Note that ApplicationPool is just an interface (i.e. a pure virtual class).</span>
101
+ <a name="l00084"></a>00084 <span class="comment"> * For concrete classes, see StandardApplicationPool and ApplicationPoolServer.</span>
102
+ <a name="l00085"></a>00085 <span class="comment"> * The exact pooling algorithm depends on the implementation class.</span>
103
+ <a name="l00086"></a>00086 <span class="comment"> *</span>
104
+ <a name="l00087"></a>00087 <span class="comment"> * @ingroup Support</span>
105
+ <a name="l00088"></a>00088 <span class="comment"> */</span>
106
+ <a name="l00089"></a><a class="code" href="classPassenger_1_1ApplicationPool.html">00089</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1ApplicationPool.html" title="A persistent pool of Applications.">ApplicationPool</a> {
107
+ <a name="l00090"></a>00090 <span class="keyword">public</span>:
108
+ <a name="l00091"></a>00091 <span class="keyword">virtual</span> ~<a class="code" href="classPassenger_1_1ApplicationPool.html" title="A persistent pool of Applications.">ApplicationPool</a>() {};
109
+ <a name="l00092"></a>00092 <span class="comment"></span>
110
+ <a name="l00093"></a>00093 <span class="comment"> /**</span>
111
+ <a name="l00094"></a>00094 <span class="comment"> * Open a new session with the application specified by &lt;tt&gt;appRoot&lt;/tt&gt;.</span>
112
+ <a name="l00095"></a>00095 <span class="comment"> * See the class description for ApplicationPool, as well as Application::connect(),</span>
113
+ <a name="l00096"></a>00096 <span class="comment"> * on how to use the returned session object.</span>
114
+ <a name="l00097"></a>00097 <span class="comment"> *</span>
115
+ <a name="l00098"></a>00098 <span class="comment"> * Internally, this method may either spawn a new application instance, or use</span>
116
+ <a name="l00099"></a>00099 <span class="comment"> * an existing one.</span>
117
+ <a name="l00100"></a>00100 <span class="comment"> *</span>
118
+ <a name="l00101"></a>00101 <span class="comment"> * If &lt;tt&gt;lowerPrivilege&lt;/tt&gt; is true, then any newly spawned application</span>
119
+ <a name="l00102"></a>00102 <span class="comment"> * instances will have lower privileges. See SpawnManager::SpawnManager()'s</span>
120
+ <a name="l00103"></a>00103 <span class="comment"> * description of &lt;tt&gt;lowerPrivilege&lt;/tt&gt; and &lt;tt&gt;lowestUser&lt;/tt&gt; for details.</span>
121
+ <a name="l00104"></a>00104 <span class="comment"> *</span>
122
+ <a name="l00105"></a>00105 <span class="comment"> * @param appRoot The application root of a RoR application, i.e. the folder that</span>
123
+ <a name="l00106"></a>00106 <span class="comment"> * contains 'app/', 'public/', 'config/', etc. This must be a valid</span>
124
+ <a name="l00107"></a>00107 <span class="comment"> * directory, but does not have to be an absolute path.</span>
125
+ <a name="l00108"></a>00108 <span class="comment"> * @param lowerPrivilege Whether to lower the application's privileges.</span>
126
+ <a name="l00109"></a>00109 <span class="comment"> * @param lowestUser The user to fallback to if lowering privilege fails.</span>
127
+ <a name="l00110"></a>00110 <span class="comment"> * @param environment The RAILS_ENV/RACK_ENV environment that should be used. May not be empty.</span>
128
+ <a name="l00111"></a>00111 <span class="comment"> * @param spawnMethod The spawn method to use. Either "smart" or "conservative".</span>
129
+ <a name="l00112"></a>00112 <span class="comment"> * See the Ruby class SpawnManager for details.</span>
130
+ <a name="l00113"></a>00113 <span class="comment"> * @param appType The application type. Either "rails" or "rack".</span>
131
+ <a name="l00114"></a>00114 <span class="comment"> * @return A session object.</span>
132
+ <a name="l00115"></a>00115 <span class="comment"> * @throw SpawnException An attempt was made to spawn a new application instance, but that attempt failed.</span>
133
+ <a name="l00116"></a>00116 <span class="comment"> * @throw BusyException The application pool is too busy right now, and cannot</span>
134
+ <a name="l00117"></a>00117 <span class="comment"> * satisfy the request. One should either abort, or try again later.</span>
135
+ <a name="l00118"></a>00118 <span class="comment"> * @throw IOException Something else went wrong.</span>
136
+ <a name="l00119"></a>00119 <span class="comment"> * @throw thread_interrupted</span>
137
+ <a name="l00120"></a>00120 <span class="comment"> * @note Applications are uniquely identified with the application root</span>
138
+ <a name="l00121"></a>00121 <span class="comment"> * string. So although &lt;tt&gt;appRoot&lt;/tt&gt; does not have to be absolute, it</span>
139
+ <a name="l00122"></a>00122 <span class="comment"> * should be. If one calls &lt;tt&gt;get("/home/foo")&lt;/tt&gt; and</span>
140
+ <a name="l00123"></a>00123 <span class="comment"> * &lt;tt&gt;get("/home/../home/foo")&lt;/tt&gt;, then ApplicationPool will think</span>
141
+ <a name="l00124"></a>00124 <span class="comment"> * they're 2 different applications, and thus will spawn 2 application instances.</span>
142
+ <a name="l00125"></a>00125 <span class="comment"> */</span>
143
+ <a name="l00126"></a>00126 <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, <span class="keywordtype">bool</span> lowerPrivilege = <span class="keyword">true</span>,
144
+ <a name="l00127"></a>00127 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;lowestUser = <span class="stringliteral">"nobody"</span>, <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;environment = <span class="stringliteral">"production"</span>,
145
+ <a name="l00128"></a>00128 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;spawnMethod = <span class="stringliteral">"smart"</span>, <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;appType = <span class="stringliteral">"rails"</span>) = 0;
146
+ <a name="l00129"></a>00129 <span class="comment"></span>
147
+ <a name="l00130"></a>00130 <span class="comment"> /**</span>
148
+ <a name="l00131"></a>00131 <span class="comment"> * Clear all application instances that are currently in the pool.</span>
149
+ <a name="l00132"></a>00132 <span class="comment"> *</span>
150
+ <a name="l00133"></a>00133 <span class="comment"> * This method is used by unit tests to verify that the implementation is correct,</span>
151
+ <a name="l00134"></a>00134 <span class="comment"> * and thus should not be called directly.</span>
152
+ <a name="l00135"></a>00135 <span class="comment"> */</span>
153
+ <a name="l00136"></a>00136 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#74db4d7a693d45b16320b2296a0c0997" title="Clear all application instances that are currently in the pool.">clear</a>() = 0;
154
+ <a name="l00137"></a>00137
155
+ <a name="l00138"></a>00138 <span class="keyword">virtual</span> <span class="keywordtype">void</span> setMaxIdleTime(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seconds) = 0;
156
+ <a name="l00139"></a>00139 <span class="comment"></span>
157
+ <a name="l00140"></a>00140 <span class="comment"> /**</span>
158
+ <a name="l00141"></a>00141 <span class="comment"> * Set a hard limit on the number of application instances that this ApplicationPool</span>
159
+ <a name="l00142"></a>00142 <span class="comment"> * may spawn. The exact behavior depends on the used algorithm, and is not specified by</span>
160
+ <a name="l00143"></a>00143 <span class="comment"> * these API docs.</span>
161
+ <a name="l00144"></a>00144 <span class="comment"> *</span>
162
+ <a name="l00145"></a>00145 <span class="comment"> * It is allowed to set a limit lower than the current number of spawned applications.</span>
163
+ <a name="l00146"></a>00146 <span class="comment"> */</span>
164
+ <a name="l00147"></a>00147 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#0e0f21972ab130c9c0f90c2212328794" 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) = 0;
165
+ <a name="l00148"></a>00148 <span class="comment"></span>
166
+ <a name="l00149"></a>00149 <span class="comment"> /**</span>
167
+ <a name="l00150"></a>00150 <span class="comment"> * Get the number of active applications in the pool.</span>
168
+ <a name="l00151"></a>00151 <span class="comment"> *</span>
169
+ <a name="l00152"></a>00152 <span class="comment"> * This method exposes an implementation detail of the underlying pooling algorithm.</span>
170
+ <a name="l00153"></a>00153 <span class="comment"> * It is used by unit tests to verify that the implementation is correct,</span>
171
+ <a name="l00154"></a>00154 <span class="comment"> * and thus should not be called directly.</span>
172
+ <a name="l00155"></a>00155 <span class="comment"> */</span>
173
+ <a name="l00156"></a>00156 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#06d1eae044d4d761ce77cf09049df8c8" title="Get the number of active applications in the pool.">getActive</a>() <span class="keyword">const</span> = 0;
174
+ <a name="l00157"></a>00157 <span class="comment"></span>
175
+ <a name="l00158"></a>00158 <span class="comment"> /**</span>
176
+ <a name="l00159"></a>00159 <span class="comment"> * Get the number of active applications in the pool.</span>
177
+ <a name="l00160"></a>00160 <span class="comment"> *</span>
178
+ <a name="l00161"></a>00161 <span class="comment"> * This method exposes an implementation detail of the underlying pooling algorithm.</span>
179
+ <a name="l00162"></a>00162 <span class="comment"> * It is used by unit tests to verify that the implementation is correct,</span>
180
+ <a name="l00163"></a>00163 <span class="comment"> * and thus should not be called directly.</span>
181
+ <a name="l00164"></a>00164 <span class="comment"> */</span>
182
+ <a name="l00165"></a>00165 <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#93b0277beb510855f85fee5de5c369bb" title="Get the number of active applications in the pool.">getCount</a>() <span class="keyword">const</span> = 0;
183
+ <a name="l00166"></a>00166 <span class="comment"></span>
184
+ <a name="l00167"></a>00167 <span class="comment"> /**</span>
185
+ <a name="l00168"></a>00168 <span class="comment"> * Set a hard limit on the number of application instances that a single application</span>
186
+ <a name="l00169"></a>00169 <span class="comment"> * may spawn in this ApplicationPool. The exact behavior depends on the used algorithm, </span>
187
+ <a name="l00170"></a>00170 <span class="comment"> * and is not specified by these API docs.</span>
188
+ <a name="l00171"></a>00171 <span class="comment"> *</span>
189
+ <a name="l00172"></a>00172 <span class="comment"> * It is allowed to set a limit lower than the current number of spawned applications.</span>
190
+ <a name="l00173"></a>00173 <span class="comment"> */</span>
191
+ <a name="l00174"></a>00174 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#b0437434c79b5444ac0faf768f1410e8" 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> max) = 0;
192
+ <a name="l00175"></a>00175 <span class="comment"></span>
193
+ <a name="l00176"></a>00176 <span class="comment"> /**</span>
194
+ <a name="l00177"></a>00177 <span class="comment"> * Sets whether to use a global queue instead of a per-backend process</span>
195
+ <a name="l00178"></a>00178 <span class="comment"> * queue. If enabled, when all backend processes are active, get() will</span>
196
+ <a name="l00179"></a>00179 <span class="comment"> * wait until there's at least one backend process that's idle, instead</span>
197
+ <a name="l00180"></a>00180 <span class="comment"> * of queuing the request into a random process's private queue.</span>
198
+ <a name="l00181"></a>00181 <span class="comment"> * This is especially useful if a website has one or more long-running</span>
199
+ <a name="l00182"></a>00182 <span class="comment"> * requests.</span>
200
+ <a name="l00183"></a>00183 <span class="comment"> *</span>
201
+ <a name="l00184"></a>00184 <span class="comment"> * Defaults to false.</span>
202
+ <a name="l00185"></a>00185 <span class="comment"> */</span>
203
+ <a name="l00186"></a>00186 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1ApplicationPool.html#b5faf64421313e1387c187f80b95d0e7" title="Sets whether to use a global queue instead of a per-backend process queue.">setUseGlobalQueue</a>(<span class="keywordtype">bool</span> value) = 0;
204
+ <a name="l00187"></a>00187 <span class="comment"></span>
205
+ <a name="l00188"></a>00188 <span class="comment"> /**</span>
206
+ <a name="l00189"></a>00189 <span class="comment"> * Get the process ID of the spawn server that is used.</span>
207
+ <a name="l00190"></a>00190 <span class="comment"> *</span>
208
+ <a name="l00191"></a>00191 <span class="comment"> * This method exposes an implementation detail. It is used by unit tests to verify</span>
209
+ <a name="l00192"></a>00192 <span class="comment"> * that the implementation is correct, and thus should not be used directly.</span>
210
+ <a name="l00193"></a>00193 <span class="comment"> */</span>
211
+ <a name="l00194"></a>00194 <span class="keyword">virtual</span> pid_t <a class="code" href="classPassenger_1_1ApplicationPool.html#d9149c3b434ef8e18fd15a77af1a6c2c" title="Get the process ID of the spawn server that is used.">getSpawnServerPid</a>() <span class="keyword">const</span> = 0;
212
+ <a name="l00195"></a>00195 };
213
+ <a name="l00196"></a>00196
214
+ <a name="l00197"></a>00197 <span class="keyword">typedef</span> shared_ptr&lt;ApplicationPool&gt; ApplicationPoolPtr;
215
+ <a name="l00198"></a>00198
216
+ <a name="l00199"></a>00199 }; <span class="comment">// namespace Passenger</span>
217
+ <a name="l00200"></a>00200
218
+ <a name="l00201"></a>00201 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_POOL_H_ */</span>
219
+ </pre></div></div>
220
+ <hr size="1"><address style="text-align: right;"><small>Generated on Mon Dec 1 14:27:22 2008 for Passenger by&nbsp;
221
+ <a href="http://www.doxygen.org/index.html">
222
+ <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
223
+ </body>
224
+ </html>
@@ -0,0 +1,448 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
3
+ <title>Passenger: Application.h Source File</title>
4
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
5
+ <link href="tabs.css" rel="stylesheet" type="text/css">
6
+ </head><body>
7
+ <!-- Generated by Doxygen 1.5.5 -->
8
+ <div class="navigation" id="top">
9
+ <div class="tabs">
10
+ <ul>
11
+ <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
12
+ <li><a href="modules.html"><span>Modules</span></a></li>
13
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
14
+ <li><a href="annotated.html"><span>Classes</span></a></li>
15
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
16
+ </ul>
17
+ </div>
18
+ <h1>Application.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
19
+ <a name="l00002"></a>00002 <span class="comment"> * Phusion Passenger - http://www.modrails.com/</span>
20
+ <a name="l00003"></a>00003 <span class="comment"> * Copyright (C) 2008 Phusion</span>
21
+ <a name="l00004"></a>00004 <span class="comment"> *</span>
22
+ <a name="l00005"></a>00005 <span class="comment"> * Phusion Passenger is a trademark of Hongli Lai &amp; Ninh Bui.</span>
23
+ <a name="l00006"></a>00006 <span class="comment"> *</span>
24
+ <a name="l00007"></a>00007 <span class="comment"> * This program is free software; you can redistribute it and/or modify</span>
25
+ <a name="l00008"></a>00008 <span class="comment"> * it under the terms of the GNU General Public License as published by</span>
26
+ <a name="l00009"></a>00009 <span class="comment"> * the Free Software Foundation; version 2 of the License.</span>
27
+ <a name="l00010"></a>00010 <span class="comment"> *</span>
28
+ <a name="l00011"></a>00011 <span class="comment"> * This program is distributed in the hope that it will be useful,</span>
29
+ <a name="l00012"></a>00012 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
30
+ <a name="l00013"></a>00013 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
31
+ <a name="l00014"></a>00014 <span class="comment"> * GNU General Public License for more details.</span>
32
+ <a name="l00015"></a>00015 <span class="comment"> *</span>
33
+ <a name="l00016"></a>00016 <span class="comment"> * You should have received a copy of the GNU General Public License along</span>
34
+ <a name="l00017"></a>00017 <span class="comment"> * with this program; if not, write to the Free Software Foundation, Inc.,</span>
35
+ <a name="l00018"></a>00018 <span class="comment"> * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span>
36
+ <a name="l00019"></a>00019 <span class="comment"> */</span>
37
+ <a name="l00020"></a>00020 <span class="preprocessor">#ifndef _PASSENGER_APPLICATION_H_</span>
38
+ <a name="l00021"></a>00021 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_APPLICATION_H_</span>
39
+ <a name="l00022"></a>00022 <span class="preprocessor"></span>
40
+ <a name="l00023"></a>00023 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
41
+ <a name="l00024"></a>00024 <span class="preprocessor">#include &lt;boost/function.hpp&gt;</span>
42
+ <a name="l00025"></a>00025 <span class="preprocessor">#include &lt;string&gt;</span>
43
+ <a name="l00026"></a>00026
44
+ <a name="l00027"></a>00027 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
45
+ <a name="l00028"></a>00028 <span class="preprocessor">#include &lt;sys/socket.h&gt;</span>
46
+ <a name="l00029"></a>00029 <span class="preprocessor">#include &lt;sys/un.h&gt;</span>
47
+ <a name="l00030"></a>00030 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
48
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;errno.h&gt;</span>
49
+ <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;ctime&gt;</span>
50
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &lt;cstring&gt;</span>
51
+ <a name="l00034"></a>00034
52
+ <a name="l00035"></a>00035 <span class="preprocessor">#include "MessageChannel.h"</span>
53
+ <a name="l00036"></a>00036 <span class="preprocessor">#include "Exceptions.h"</span>
54
+ <a name="l00037"></a>00037 <span class="preprocessor">#include "Logging.h"</span>
55
+ <a name="l00038"></a>00038
56
+ <a name="l00039"></a><a class="code" href="namespacePassenger.html">00039</a> <span class="keyword">namespace </span>Passenger {
57
+ <a name="l00040"></a>00040
58
+ <a name="l00041"></a>00041 <span class="keyword">using namespace </span>std;
59
+ <a name="l00042"></a>00042 <span class="keyword">using namespace </span>boost;
60
+ <a name="l00043"></a>00043 <span class="comment"></span>
61
+ <a name="l00044"></a>00044 <span class="comment">/**</span>
62
+ <a name="l00045"></a>00045 <span class="comment"> * Represents a single Ruby on Rails or Rack application instance.</span>
63
+ <a name="l00046"></a>00046 <span class="comment"> *</span>
64
+ <a name="l00047"></a>00047 <span class="comment"> * @ingroup Support</span>
65
+ <a name="l00048"></a>00048 <span class="comment"> */</span>
66
+ <a name="l00049"></a><a class="code" href="classPassenger_1_1Application.html">00049</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1Application.html" title="Represents a single Ruby on Rails or Rack application instance.">Application</a> {
67
+ <a name="l00050"></a>00050 <span class="keyword">public</span>:
68
+ <a name="l00051"></a><a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9">00051</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1Application_1_1Session.html" title="Represents the life time of a single request/response pair of a Ruby on Rails or...">Session</a>;<span class="comment"></span>
69
+ <a name="l00052"></a>00052 <span class="comment"> /** Convenient alias for Session smart pointer. */</span>
70
+ <a name="l00053"></a>00053 <span class="keyword">typedef</span> shared_ptr&lt;Session&gt; <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">SessionPtr</a>;
71
+ <a name="l00054"></a>00054 <span class="comment"></span>
72
+ <a name="l00055"></a>00055 <span class="comment"> /**</span>
73
+ <a name="l00056"></a>00056 <span class="comment"> * Represents the life time of a single request/response pair of a</span>
74
+ <a name="l00057"></a>00057 <span class="comment"> * Ruby on Rails or Rack application.</span>
75
+ <a name="l00058"></a>00058 <span class="comment"> *</span>
76
+ <a name="l00059"></a>00059 <span class="comment"> * Session is used to forward a single HTTP request to a Ruby on Rails/Rack</span>
77
+ <a name="l00060"></a>00060 <span class="comment"> * application. A Session has two communication channels: one for reading data</span>
78
+ <a name="l00061"></a>00061 <span class="comment"> * from the application, and one for writing data to the application.</span>
79
+ <a name="l00062"></a>00062 <span class="comment"> *</span>
80
+ <a name="l00063"></a>00063 <span class="comment"> * In general, a session object is to be used in the following manner:</span>
81
+ <a name="l00064"></a>00064 <span class="comment"> *</span>
82
+ <a name="l00065"></a>00065 <span class="comment"> * -# Convert the HTTP request headers into a string, as expected by sendHeaders().</span>
83
+ <a name="l00066"></a>00066 <span class="comment"> * Then send that string by calling sendHeaders().</span>
84
+ <a name="l00067"></a>00067 <span class="comment"> * -# In case of a POST of PUT request, send the HTTP request body by calling</span>
85
+ <a name="l00068"></a>00068 <span class="comment"> * sendBodyBlock(), possibly multiple times.</span>
86
+ <a name="l00069"></a>00069 <span class="comment"> * -# Shutdown the writer channel since you're now done sending data.</span>
87
+ <a name="l00070"></a>00070 <span class="comment"> * -# The HTTP response can now be read through the reader channel (getStream()).</span>
88
+ <a name="l00071"></a>00071 <span class="comment"> * -# When the HTTP response has been read, the session must be closed.</span>
89
+ <a name="l00072"></a>00072 <span class="comment"> * This is done by destroying the Session object.</span>
90
+ <a name="l00073"></a>00073 <span class="comment"> *</span>
91
+ <a name="l00074"></a>00074 <span class="comment"> * A usage example is shown in Application::connect(). </span>
92
+ <a name="l00075"></a>00075 <span class="comment"> */</span>
93
+ <a name="l00076"></a><a class="code" href="classPassenger_1_1Application_1_1Session.html">00076</a> <span class="keyword">class </span><a class="code" href="classPassenger_1_1Application_1_1Session.html" title="Represents the life time of a single request/response pair of a Ruby on Rails or...">Session</a> {
94
+ <a name="l00077"></a>00077 <span class="keyword">public</span>:<span class="comment"></span>
95
+ <a name="l00078"></a>00078 <span class="comment"> /**</span>
96
+ <a name="l00079"></a>00079 <span class="comment"> * Implementing classes might throw arbitrary exceptions.</span>
97
+ <a name="l00080"></a>00080 <span class="comment"> */</span>
98
+ <a name="l00081"></a><a class="code" href="classPassenger_1_1Application_1_1Session.html#4fcaf0670234f7fb2ea6de4b8d8ef38c">00081</a> <span class="keyword">virtual</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#4fcaf0670234f7fb2ea6de4b8d8ef38c" title="Implementing classes might throw arbitrary exceptions.">~Session</a>() {}
99
+ <a name="l00082"></a>00082 <span class="comment"></span>
100
+ <a name="l00083"></a>00083 <span class="comment"> /**</span>
101
+ <a name="l00084"></a>00084 <span class="comment"> * Send HTTP request headers to the application. The HTTP headers must be</span>
102
+ <a name="l00085"></a>00085 <span class="comment"> * converted into CGI headers, and then encoded into a string that matches this grammar:</span>
103
+ <a name="l00086"></a>00086 <span class="comment"> *</span>
104
+ <a name="l00087"></a>00087 <span class="comment"> @verbatim</span>
105
+ <a name="l00088"></a>00088 <span class="comment"> headers ::= header*</span>
106
+ <a name="l00089"></a>00089 <span class="comment"> header ::= name NUL value NUL</span>
107
+ <a name="l00090"></a>00090 <span class="comment"> name ::= notnull+</span>
108
+ <a name="l00091"></a>00091 <span class="comment"> value ::= notnull+</span>
109
+ <a name="l00092"></a>00092 <span class="comment"> notnull ::= "\x01" | "\x02" | "\x02" | ... | "\xFF"</span>
110
+ <a name="l00093"></a>00093 <span class="comment"> NUL = "\x00"</span>
111
+ <a name="l00094"></a>00094 <span class="comment"> @endverbatim</span>
112
+ <a name="l00095"></a>00095 <span class="comment"> *</span>
113
+ <a name="l00096"></a>00096 <span class="comment"> * This method should be the first one to be called during the lifetime of a Session</span>
114
+ <a name="l00097"></a>00097 <span class="comment"> * object. Otherwise strange things may happen.</span>
115
+ <a name="l00098"></a>00098 <span class="comment"> *</span>
116
+ <a name="l00099"></a>00099 <span class="comment"> * @param headers The HTTP request headers, converted into CGI headers and encoded as</span>
117
+ <a name="l00100"></a>00100 <span class="comment"> * a string, according to the description.</span>
118
+ <a name="l00101"></a>00101 <span class="comment"> * @param size The size, in bytes, of &lt;tt&gt;headers&lt;/tt&gt;.</span>
119
+ <a name="l00102"></a>00102 <span class="comment"> * @pre headers != NULL</span>
120
+ <a name="l00103"></a>00103 <span class="comment"> * @throws IOException The writer channel has already been closed.</span>
121
+ <a name="l00104"></a>00104 <span class="comment"> * @throws SystemException Something went wrong during writing.</span>
122
+ <a name="l00105"></a>00105 <span class="comment"> * @throws boost::thread_interrupted</span>
123
+ <a name="l00106"></a>00106 <span class="comment"> */</span>
124
+ <a name="l00107"></a><a class="code" href="classPassenger_1_1Application_1_1Session.html#78a4c93fd80f6d913f092c488ea4d360">00107</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#78a4c93fd80f6d913f092c488ea4d360" title="Send HTTP request headers to the application.">sendHeaders</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *headers, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) {
125
+ <a name="l00108"></a>00108 <span class="keywordtype">int</span> stream = <a class="code" href="classPassenger_1_1Application_1_1Session.html#2631b6d6b4927ec66b1f620df15d8c6e" title="Get the I/O stream&amp;#39;s file descriptor.">getStream</a>();
126
+ <a name="l00109"></a>00109 <span class="keywordflow">if</span> (stream == -1) {
127
+ <a name="l00110"></a>00110 <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>(<span class="stringliteral">"Cannot write headers to the request handler "</span>
128
+ <a name="l00111"></a>00111 <span class="stringliteral">"because the writer stream has already been closed."</span>);
129
+ <a name="l00112"></a>00112 }
130
+ <a name="l00113"></a>00113 <span class="keywordflow">try</span> {
131
+ <a name="l00114"></a>00114 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a>(stream).writeScalar(headers, size);
132
+ <a name="l00115"></a>00115 } <span class="keywordflow">catch</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;e) {
133
+ <a name="l00116"></a>00116 <span class="keywordflow">throw</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>(<span class="stringliteral">"An error occured while writing headers "</span>
134
+ <a name="l00117"></a>00117 <span class="stringliteral">"to the request handler"</span>, e.<a class="code" href="classPassenger_1_1SystemException.html#ee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
135
+ <a name="l00118"></a>00118 }
136
+ <a name="l00119"></a>00119 }
137
+ <a name="l00120"></a>00120 <span class="comment"></span>
138
+ <a name="l00121"></a>00121 <span class="comment"> /**</span>
139
+ <a name="l00122"></a>00122 <span class="comment"> * Convenience shortcut for sendHeaders(const char *, unsigned int)</span>
140
+ <a name="l00123"></a>00123 <span class="comment"> * @param headers</span>
141
+ <a name="l00124"></a>00124 <span class="comment"> * @throws IOException The writer channel has already been closed.</span>
142
+ <a name="l00125"></a>00125 <span class="comment"> * @throws SystemException Something went wrong during writing.</span>
143
+ <a name="l00126"></a>00126 <span class="comment"> * @throws boost::thread_interrupted</span>
144
+ <a name="l00127"></a>00127 <span class="comment"> */</span>
145
+ <a name="l00128"></a><a class="code" href="classPassenger_1_1Application_1_1Session.html#4fee03667f626d68c565495bcb19771a">00128</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#78a4c93fd80f6d913f092c488ea4d360" title="Send HTTP request headers to the application.">sendHeaders</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;headers) {
146
+ <a name="l00129"></a>00129 <a class="code" href="classPassenger_1_1Application_1_1Session.html#78a4c93fd80f6d913f092c488ea4d360" title="Send HTTP request headers to the application.">sendHeaders</a>(headers.c_str(), headers.size());
147
+ <a name="l00130"></a>00130 }
148
+ <a name="l00131"></a>00131 <span class="comment"></span>
149
+ <a name="l00132"></a>00132 <span class="comment"> /**</span>
150
+ <a name="l00133"></a>00133 <span class="comment"> * Send a chunk of HTTP request body data to the application.</span>
151
+ <a name="l00134"></a>00134 <span class="comment"> * You can call this method as many times as is required to transfer</span>
152
+ <a name="l00135"></a>00135 <span class="comment"> * the entire HTTP request body.</span>
153
+ <a name="l00136"></a>00136 <span class="comment"> *</span>
154
+ <a name="l00137"></a>00137 <span class="comment"> * This method should only be called after a sendHeaders(). Otherwise</span>
155
+ <a name="l00138"></a>00138 <span class="comment"> * strange things may happen.</span>
156
+ <a name="l00139"></a>00139 <span class="comment"> *</span>
157
+ <a name="l00140"></a>00140 <span class="comment"> * @param block A block of HTTP request body data to send.</span>
158
+ <a name="l00141"></a>00141 <span class="comment"> * @param size The size, in bytes, of &lt;tt&gt;block&lt;/tt&gt;.</span>
159
+ <a name="l00142"></a>00142 <span class="comment"> * @throws IOException The writer channel has already been closed.</span>
160
+ <a name="l00143"></a>00143 <span class="comment"> * @throws SystemException Something went wrong during writing.</span>
161
+ <a name="l00144"></a>00144 <span class="comment"> * @throws boost::thread_interrupted</span>
162
+ <a name="l00145"></a>00145 <span class="comment"> */</span>
163
+ <a name="l00146"></a><a class="code" href="classPassenger_1_1Application_1_1Session.html#2091e4b60dcbe42ab80fa387610fd669">00146</a> <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#2091e4b60dcbe42ab80fa387610fd669" title="Send a chunk of HTTP request body data to the application.">sendBodyBlock</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *block, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) {
164
+ <a name="l00147"></a>00147 <span class="keywordtype">int</span> stream = <a class="code" href="classPassenger_1_1Application_1_1Session.html#2631b6d6b4927ec66b1f620df15d8c6e" title="Get the I/O stream&amp;#39;s file descriptor.">getStream</a>();
165
+ <a name="l00148"></a>00148 <span class="keywordflow">if</span> (stream == -1) {
166
+ <a name="l00149"></a>00149 <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>(<span class="stringliteral">"Cannot write request body block to the "</span>
167
+ <a name="l00150"></a>00150 <span class="stringliteral">"request handler because the writer stream has "</span>
168
+ <a name="l00151"></a>00151 <span class="stringliteral">"already been closed."</span>);
169
+ <a name="l00152"></a>00152 }
170
+ <a name="l00153"></a>00153 <span class="keywordflow">try</span> {
171
+ <a name="l00154"></a>00154 <a class="code" href="classPassenger_1_1MessageChannel.html" title="Convenience class for I/O operations on file descriptors.">MessageChannel</a>(stream).writeRaw(block, size);
172
+ <a name="l00155"></a>00155 } <span class="keywordflow">catch</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;e) {
173
+ <a name="l00156"></a>00156 <span class="keywordflow">throw</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>(<span class="stringliteral">"An error occured while sending the "</span>
174
+ <a name="l00157"></a>00157 <span class="stringliteral">"request body to the request handler"</span>, e.<a class="code" href="classPassenger_1_1SystemException.html#ee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
175
+ <a name="l00158"></a>00158 }
176
+ <a name="l00159"></a>00159 }
177
+ <a name="l00160"></a>00160 <span class="comment"></span>
178
+ <a name="l00161"></a>00161 <span class="comment"> /**</span>
179
+ <a name="l00162"></a>00162 <span class="comment"> * Get the I/O stream's file descriptor. This steam is full-duplex,</span>
180
+ <a name="l00163"></a>00163 <span class="comment"> * and will be automatically closed upon Session's destruction,</span>
181
+ <a name="l00164"></a>00164 <span class="comment"> * unless discardStream() is called.</span>
182
+ <a name="l00165"></a>00165 <span class="comment"> *</span>
183
+ <a name="l00166"></a>00166 <span class="comment"> * @pre The stream has not been fully closed.</span>
184
+ <a name="l00167"></a>00167 <span class="comment"> */</span>
185
+ <a name="l00168"></a>00168 <span class="keyword">virtual</span> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#2631b6d6b4927ec66b1f620df15d8c6e" title="Get the I/O stream&amp;#39;s file descriptor.">getStream</a>() <span class="keyword">const</span> = 0;
186
+ <a name="l00169"></a>00169 <span class="comment"></span>
187
+ <a name="l00170"></a>00170 <span class="comment"> /**</span>
188
+ <a name="l00171"></a>00171 <span class="comment"> * Indicate that we don't want to read data anymore from the I/O stream.</span>
189
+ <a name="l00172"></a>00172 <span class="comment"> * Calling this method after closeStream() is called will have no effect.</span>
190
+ <a name="l00173"></a>00173 <span class="comment"> *</span>
191
+ <a name="l00174"></a>00174 <span class="comment"> * @throws SystemException Something went wrong.</span>
192
+ <a name="l00175"></a>00175 <span class="comment"> * @throws boost::thread_interrupted</span>
193
+ <a name="l00176"></a>00176 <span class="comment"> */</span>
194
+ <a name="l00177"></a>00177 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#45ad442dc1f4e7b73782bb3395d9e97d" title="Indicate that we don&amp;#39;t want to read data anymore from the I/O stream.">shutdownReader</a>() = 0;
195
+ <a name="l00178"></a>00178 <span class="comment"></span>
196
+ <a name="l00179"></a>00179 <span class="comment"> /**</span>
197
+ <a name="l00180"></a>00180 <span class="comment"> * Indicate that we don't want to write data anymore to the I/O stream.</span>
198
+ <a name="l00181"></a>00181 <span class="comment"> * Calling this method after closeStream() is called will have no effect.</span>
199
+ <a name="l00182"></a>00182 <span class="comment"> *</span>
200
+ <a name="l00183"></a>00183 <span class="comment"> * @throws SystemException Something went wrong.</span>
201
+ <a name="l00184"></a>00184 <span class="comment"> * @throws boost::thread_interrupted</span>
202
+ <a name="l00185"></a>00185 <span class="comment"> */</span>
203
+ <a name="l00186"></a>00186 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#dff449398adb872c93a9572ae4b701fb" title="Indicate that we don&amp;#39;t want to write data anymore to the I/O stream.">shutdownWriter</a>() = 0;
204
+ <a name="l00187"></a>00187 <span class="comment"></span>
205
+ <a name="l00188"></a>00188 <span class="comment"> /**</span>
206
+ <a name="l00189"></a>00189 <span class="comment"> * Close the I/O stream.</span>
207
+ <a name="l00190"></a>00190 <span class="comment"> *</span>
208
+ <a name="l00191"></a>00191 <span class="comment"> * @throws SystemException Something went wrong.</span>
209
+ <a name="l00192"></a>00192 <span class="comment"> * @throws boost::thread_interrupted</span>
210
+ <a name="l00193"></a>00193 <span class="comment"> */</span>
211
+ <a name="l00194"></a>00194 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#ddfeda914b17749a70016f5eb384f8a9" title="Close the I/O stream.">closeStream</a>() = 0;
212
+ <a name="l00195"></a>00195 <span class="comment"></span>
213
+ <a name="l00196"></a>00196 <span class="comment"> /**</span>
214
+ <a name="l00197"></a>00197 <span class="comment"> * Discard the I/O stream's file descriptor, so that Session won't automatically</span>
215
+ <a name="l00198"></a>00198 <span class="comment"> * closed it upon Session's destruction.</span>
216
+ <a name="l00199"></a>00199 <span class="comment"> */</span>
217
+ <a name="l00200"></a>00200 <span class="keyword">virtual</span> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1Application_1_1Session.html#7f9ad70e75d21130d914d2134061c757" title="Discard the I/O stream&amp;#39;s file descriptor, so that Session won&amp;#39;t automatically...">discardStream</a>() = 0;
218
+ <a name="l00201"></a>00201 <span class="comment"></span>
219
+ <a name="l00202"></a>00202 <span class="comment"> /**</span>
220
+ <a name="l00203"></a>00203 <span class="comment"> * Get the process ID of the application instance that belongs to this session.</span>
221
+ <a name="l00204"></a>00204 <span class="comment"> */</span>
222
+ <a name="l00205"></a>00205 <span class="keyword">virtual</span> pid_t <a class="code" href="classPassenger_1_1Application_1_1Session.html#2215bec32917c48d1a9f6386b88d018b" title="Get the process ID of the application instance that belongs to this session.">getPid</a>() <span class="keyword">const</span> = 0;
223
+ <a name="l00206"></a>00206 };
224
+ <a name="l00207"></a>00207
225
+ <a name="l00208"></a>00208 <span class="keyword">private</span>:<span class="comment"></span>
226
+ <a name="l00209"></a>00209 <span class="comment"> /**</span>
227
+ <a name="l00210"></a>00210 <span class="comment"> * A "standard" implementation of Session.</span>
228
+ <a name="l00211"></a>00211 <span class="comment"> */</span>
229
+ <a name="l00212"></a>00212 <span class="keyword">class </span>StandardSession: <span class="keyword">public</span> Session {
230
+ <a name="l00213"></a>00213 <span class="keyword">protected</span>:
231
+ <a name="l00214"></a>00214 function&lt;void()&gt; closeCallback;
232
+ <a name="l00215"></a>00215 <span class="keywordtype">int</span> fd;
233
+ <a name="l00216"></a>00216 pid_t pid;
234
+ <a name="l00217"></a>00217
235
+ <a name="l00218"></a>00218 <span class="keyword">public</span>:
236
+ <a name="l00219"></a>00219 StandardSession(pid_t pid,
237
+ <a name="l00220"></a>00220 <span class="keyword">const</span> function&lt;<span class="keywordtype">void</span>()&gt; &amp;closeCallback,
238
+ <a name="l00221"></a>00221 <span class="keywordtype">int</span> fd) {
239
+ <a name="l00222"></a>00222 this-&gt;pid = pid;
240
+ <a name="l00223"></a>00223 this-&gt;closeCallback = closeCallback;
241
+ <a name="l00224"></a>00224 this-&gt;fd = fd;
242
+ <a name="l00225"></a>00225 }
243
+ <a name="l00226"></a>00226
244
+ <a name="l00227"></a>00227 <span class="keyword">virtual</span> ~StandardSession() {
245
+ <a name="l00228"></a>00228 closeStream();
246
+ <a name="l00229"></a>00229 closeCallback();
247
+ <a name="l00230"></a>00230 }
248
+ <a name="l00231"></a>00231
249
+ <a name="l00232"></a>00232 <span class="keyword">virtual</span> <span class="keywordtype">int</span> getStream()<span class="keyword"> const </span>{
250
+ <a name="l00233"></a>00233 <span class="keywordflow">return</span> fd;
251
+ <a name="l00234"></a>00234 }
252
+ <a name="l00235"></a>00235
253
+ <a name="l00236"></a>00236 <span class="keyword">virtual</span> <span class="keywordtype">void</span> shutdownReader() {
254
+ <a name="l00237"></a>00237 <span class="keywordflow">if</span> (fd != -1) {
255
+ <a name="l00238"></a>00238 <span class="keywordtype">int</span> ret = InterruptableCalls::shutdown(fd, SHUT_RD);
256
+ <a name="l00239"></a>00239 <span class="keywordflow">if</span> (ret == -1) {
257
+ <a name="l00240"></a>00240 <span class="keywordflow">throw</span> SystemException(<span class="stringliteral">"Cannot shutdown the writer stream"</span>,
258
+ <a name="l00241"></a>00241 errno);
259
+ <a name="l00242"></a>00242 }
260
+ <a name="l00243"></a>00243 }
261
+ <a name="l00244"></a>00244 }
262
+ <a name="l00245"></a>00245
263
+ <a name="l00246"></a>00246 <span class="keyword">virtual</span> <span class="keywordtype">void</span> shutdownWriter() {
264
+ <a name="l00247"></a>00247 <span class="keywordflow">if</span> (fd != -1) {
265
+ <a name="l00248"></a>00248 <span class="keywordtype">int</span> ret = InterruptableCalls::shutdown(fd, SHUT_WR);
266
+ <a name="l00249"></a>00249 <span class="keywordflow">if</span> (ret == -1) {
267
+ <a name="l00250"></a>00250 <span class="keywordflow">throw</span> SystemException(<span class="stringliteral">"Cannot shutdown the writer stream"</span>,
268
+ <a name="l00251"></a>00251 errno);
269
+ <a name="l00252"></a>00252 }
270
+ <a name="l00253"></a>00253 }
271
+ <a name="l00254"></a>00254 }
272
+ <a name="l00255"></a>00255
273
+ <a name="l00256"></a>00256 <span class="keyword">virtual</span> <span class="keywordtype">void</span> closeStream() {
274
+ <a name="l00257"></a>00257 <span class="keywordflow">if</span> (fd != -1) {
275
+ <a name="l00258"></a>00258 <span class="keywordtype">int</span> ret = InterruptableCalls::close(fd);
276
+ <a name="l00259"></a>00259 <span class="keywordflow">if</span> (ret == -1) {
277
+ <a name="l00260"></a>00260 <span class="keywordflow">throw</span> SystemException(<span class="stringliteral">"Cannot close the session stream"</span>,
278
+ <a name="l00261"></a>00261 errno);
279
+ <a name="l00262"></a>00262 }
280
+ <a name="l00263"></a>00263 fd = -1;
281
+ <a name="l00264"></a>00264 }
282
+ <a name="l00265"></a>00265 }
283
+ <a name="l00266"></a>00266
284
+ <a name="l00267"></a>00267 <span class="keyword">virtual</span> <span class="keywordtype">void</span> discardStream() {
285
+ <a name="l00268"></a>00268 fd = -1;
286
+ <a name="l00269"></a>00269 }
287
+ <a name="l00270"></a>00270
288
+ <a name="l00271"></a>00271 <span class="keyword">virtual</span> pid_t <a class="code" href="classPassenger_1_1Application.html#94d2cce1c2c1d3441325f1498a22bf02" title="Returns the process ID of this application instance.">getPid</a>()<span class="keyword"> const </span>{
289
+ <a name="l00272"></a>00272 <span class="keywordflow">return</span> pid;
290
+ <a name="l00273"></a>00273 }
291
+ <a name="l00274"></a>00274 };
292
+ <a name="l00275"></a>00275
293
+ <a name="l00276"></a>00276 <span class="keywordtype">string</span> appRoot;
294
+ <a name="l00277"></a>00277 pid_t pid;
295
+ <a name="l00278"></a>00278 <span class="keywordtype">string</span> listenSocketName;
296
+ <a name="l00279"></a>00279 <span class="keywordtype">bool</span> usingAbstractNamespace;
297
+ <a name="l00280"></a>00280 <span class="keywordtype">int</span> ownerPipe;
298
+ <a name="l00281"></a>00281
299
+ <a name="l00282"></a>00282 <span class="keyword">public</span>:<span class="comment"></span>
300
+ <a name="l00283"></a>00283 <span class="comment"> /**</span>
301
+ <a name="l00284"></a>00284 <span class="comment"> * Construct a new Application object.</span>
302
+ <a name="l00285"></a>00285 <span class="comment"> *</span>
303
+ <a name="l00286"></a>00286 <span class="comment"> * @param theAppRoot The application root of an application. In case of a Rails application,</span>
304
+ <a name="l00287"></a>00287 <span class="comment"> * this is the folder that contains 'app/', 'public/', 'config/', etc.</span>
305
+ <a name="l00288"></a>00288 <span class="comment"> * This must be a valid directory, but the path does not have to be absolute.</span>
306
+ <a name="l00289"></a>00289 <span class="comment"> * @param pid The process ID of this application instance.</span>
307
+ <a name="l00290"></a>00290 <span class="comment"> * @param listenSocketName The name of the listener socket of this application instance.</span>
308
+ <a name="l00291"></a>00291 <span class="comment"> * @param usingAbstractNamespace Whether &lt;tt&gt;listenSocketName&lt;/tt&gt; refers to a Unix</span>
309
+ <a name="l00292"></a>00292 <span class="comment"> * socket on the abstract namespace. Note that listenSocketName must not</span>
310
+ <a name="l00293"></a>00293 <span class="comment"> * contain the leading null byte, even if it's an abstract namespace socket.</span>
311
+ <a name="l00294"></a>00294 <span class="comment"> * @param ownerPipe The owner pipe of this application instance.</span>
312
+ <a name="l00295"></a>00295 <span class="comment"> * @post getAppRoot() == theAppRoot &amp;&amp; getPid() == pid</span>
313
+ <a name="l00296"></a>00296 <span class="comment"> */</span>
314
+ <a name="l00297"></a><a class="code" href="classPassenger_1_1Application.html#163509167eef118470b72661ac8acd5d">00297</a> <a class="code" href="classPassenger_1_1Application.html#163509167eef118470b72661ac8acd5d" title="Construct a new Application object.">Application</a>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;theAppRoot, pid_t pid, <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;listenSocketName,
315
+ <a name="l00298"></a>00298 <span class="keywordtype">bool</span> usingAbstractNamespace, <span class="keywordtype">int</span> ownerPipe) {
316
+ <a name="l00299"></a>00299 appRoot = theAppRoot;
317
+ <a name="l00300"></a>00300 this-&gt;pid = pid;
318
+ <a name="l00301"></a>00301 this-&gt;listenSocketName = listenSocketName;
319
+ <a name="l00302"></a>00302 this-&gt;usingAbstractNamespace = usingAbstractNamespace;
320
+ <a name="l00303"></a>00303 this-&gt;ownerPipe = ownerPipe;
321
+ <a name="l00304"></a>00304 P_TRACE(3, <span class="stringliteral">"Application "</span> &lt;&lt; <span class="keyword">this</span> &lt;&lt; <span class="stringliteral">": created."</span>);
322
+ <a name="l00305"></a>00305 }
323
+ <a name="l00306"></a>00306
324
+ <a name="l00307"></a>00307 <span class="keyword">virtual</span> ~<a class="code" href="classPassenger_1_1Application.html" title="Represents a single Ruby on Rails or Rack application instance.">Application</a>() {
325
+ <a name="l00308"></a>00308 <span class="keywordtype">int</span> ret;
326
+ <a name="l00309"></a>00309
327
+ <a name="l00310"></a>00310 <span class="keywordflow">if</span> (ownerPipe != -1) {
328
+ <a name="l00311"></a>00311 <span class="keywordflow">do</span> {
329
+ <a name="l00312"></a>00312 ret = close(ownerPipe);
330
+ <a name="l00313"></a>00313 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
331
+ <a name="l00314"></a>00314 }
332
+ <a name="l00315"></a>00315 <span class="keywordflow">if</span> (!usingAbstractNamespace) {
333
+ <a name="l00316"></a>00316 <span class="keywordflow">do</span> {
334
+ <a name="l00317"></a>00317 ret = unlink(listenSocketName.c_str());
335
+ <a name="l00318"></a>00318 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
336
+ <a name="l00319"></a>00319 }
337
+ <a name="l00320"></a>00320 P_TRACE(3, <span class="stringliteral">"Application "</span> &lt;&lt; <span class="keyword">this</span> &lt;&lt; <span class="stringliteral">": destroyed."</span>);
338
+ <a name="l00321"></a>00321 }
339
+ <a name="l00322"></a>00322 <span class="comment"></span>
340
+ <a name="l00323"></a>00323 <span class="comment"> /**</span>
341
+ <a name="l00324"></a>00324 <span class="comment"> * Returns the application root for this application. See the constructor</span>
342
+ <a name="l00325"></a>00325 <span class="comment"> * for information about the application root.</span>
343
+ <a name="l00326"></a>00326 <span class="comment"> */</span>
344
+ <a name="l00327"></a><a class="code" href="classPassenger_1_1Application.html#0a0665852e7ebc8fb8ab0772fa90bc56">00327</a> <span class="keywordtype">string</span> <a class="code" href="classPassenger_1_1Application.html#0a0665852e7ebc8fb8ab0772fa90bc56" title="Returns the application root for this application.">getAppRoot</a>()<span class="keyword"> const </span>{
345
+ <a name="l00328"></a>00328 <span class="keywordflow">return</span> appRoot;
346
+ <a name="l00329"></a>00329 }
347
+ <a name="l00330"></a>00330 <span class="comment"></span>
348
+ <a name="l00331"></a>00331 <span class="comment"> /**</span>
349
+ <a name="l00332"></a>00332 <span class="comment"> * Returns the process ID of this application instance.</span>
350
+ <a name="l00333"></a>00333 <span class="comment"> */</span>
351
+ <a name="l00334"></a><a class="code" href="classPassenger_1_1Application.html#94d2cce1c2c1d3441325f1498a22bf02">00334</a> pid_t <a class="code" href="classPassenger_1_1Application.html#94d2cce1c2c1d3441325f1498a22bf02" title="Returns the process ID of this application instance.">getPid</a>()<span class="keyword"> const </span>{
352
+ <a name="l00335"></a>00335 <span class="keywordflow">return</span> pid;
353
+ <a name="l00336"></a>00336 }
354
+ <a name="l00337"></a>00337 <span class="comment"></span>
355
+ <a name="l00338"></a>00338 <span class="comment"> /**</span>
356
+ <a name="l00339"></a>00339 <span class="comment"> * Connect to this application instance with the purpose of sending</span>
357
+ <a name="l00340"></a>00340 <span class="comment"> * a request to the application. Once connected, a new session will</span>
358
+ <a name="l00341"></a>00341 <span class="comment"> * be opened. This session represents the life time of a single</span>
359
+ <a name="l00342"></a>00342 <span class="comment"> * request/response pair, and can be used to send the request</span>
360
+ <a name="l00343"></a>00343 <span class="comment"> * data to the application instance, as well as receiving the response</span>
361
+ <a name="l00344"></a>00344 <span class="comment"> * data.</span>
362
+ <a name="l00345"></a>00345 <span class="comment"> *</span>
363
+ <a name="l00346"></a>00346 <span class="comment"> * The use of connect() is demonstrated in the following example.</span>
364
+ <a name="l00347"></a>00347 <span class="comment"> * @code</span>
365
+ <a name="l00348"></a>00348 <span class="comment"> * // Connect to the application and get the newly opened session.</span>
366
+ <a name="l00349"></a>00349 <span class="comment"> * Application::SessionPtr session(app-&gt;connect("/home/webapps/foo"));</span>
367
+ <a name="l00350"></a>00350 <span class="comment"> * </span>
368
+ <a name="l00351"></a>00351 <span class="comment"> * // Send the request headers and request body data.</span>
369
+ <a name="l00352"></a>00352 <span class="comment"> * session-&gt;sendHeaders(...);</span>
370
+ <a name="l00353"></a>00353 <span class="comment"> * session-&gt;sendBodyBlock(...);</span>
371
+ <a name="l00354"></a>00354 <span class="comment"> * // Done sending data, so we close the writer channel.</span>
372
+ <a name="l00355"></a>00355 <span class="comment"> * session-&gt;closeWriter();</span>
373
+ <a name="l00356"></a>00356 <span class="comment"> *</span>
374
+ <a name="l00357"></a>00357 <span class="comment"> * // Now read the HTTP response.</span>
375
+ <a name="l00358"></a>00358 <span class="comment"> * string responseData = readAllDataFromSocket(session-&gt;getReader());</span>
376
+ <a name="l00359"></a>00359 <span class="comment"> * // Done reading data, so we close the reader channel.</span>
377
+ <a name="l00360"></a>00360 <span class="comment"> * session-&gt;closeReader();</span>
378
+ <a name="l00361"></a>00361 <span class="comment"> *</span>
379
+ <a name="l00362"></a>00362 <span class="comment"> * // This session has now finished, so we close the session by resetting</span>
380
+ <a name="l00363"></a>00363 <span class="comment"> * // the smart pointer to NULL (thereby destroying the Session object).</span>
381
+ <a name="l00364"></a>00364 <span class="comment"> * session.reset();</span>
382
+ <a name="l00365"></a>00365 <span class="comment"> *</span>
383
+ <a name="l00366"></a>00366 <span class="comment"> * // We can connect to an Application multiple times. Just make sure</span>
384
+ <a name="l00367"></a>00367 <span class="comment"> * // the previous session is closed.</span>
385
+ <a name="l00368"></a>00368 <span class="comment"> * session = app-&gt;connect("/home/webapps/bar")</span>
386
+ <a name="l00369"></a>00369 <span class="comment"> * @endcode</span>
387
+ <a name="l00370"></a>00370 <span class="comment"> *</span>
388
+ <a name="l00371"></a>00371 <span class="comment"> * Note that a RoR application instance can only process one</span>
389
+ <a name="l00372"></a>00372 <span class="comment"> * request at the same time, and thus only one session at the same time.</span>
390
+ <a name="l00373"></a>00373 <span class="comment"> * It's unspecified whether Rack applications can handle multiple simultanous sessions.</span>
391
+ <a name="l00374"></a>00374 <span class="comment"> *</span>
392
+ <a name="l00375"></a>00375 <span class="comment"> * You &lt;b&gt;must&lt;/b&gt; close a session when you no longer need if. If you</span>
393
+ <a name="l00376"></a>00376 <span class="comment"> * call connect() without having properly closed a previous session,</span>
394
+ <a name="l00377"></a>00377 <span class="comment"> * you might cause a deadlock because the application instance may be</span>
395
+ <a name="l00378"></a>00378 <span class="comment"> * waiting for you to close the previous session.</span>
396
+ <a name="l00379"></a>00379 <span class="comment"> *</span>
397
+ <a name="l00380"></a>00380 <span class="comment"> * @return A smart pointer to a Session object, which represents the created session.</span>
398
+ <a name="l00381"></a>00381 <span class="comment"> * @param closeCallback A function which will be called when the session has been closed.</span>
399
+ <a name="l00382"></a>00382 <span class="comment"> * @post this-&gt;getSessions() == old-&gt;getSessions() + 1</span>
400
+ <a name="l00383"></a>00383 <span class="comment"> * @throws SystemException Something went wrong during the connection process.</span>
401
+ <a name="l00384"></a>00384 <span class="comment"> * @throws IOException Something went wrong during the connection process.</span>
402
+ <a name="l00385"></a>00385 <span class="comment"> */</span>
403
+ <a name="l00386"></a><a class="code" href="classPassenger_1_1Application.html#34636f796ff3924ad5ec142aaa581379">00386</a> <a class="code" href="classPassenger_1_1Application.html#d14f673494991460b16246a527ad8ad9" title="Convenient alias for Session smart pointer.">SessionPtr</a> <a class="code" href="classPassenger_1_1Application.html#34636f796ff3924ad5ec142aaa581379" title="Connect to this application instance with the purpose of sending a request to the...">connect</a>(<span class="keyword">const</span> function&lt;<span class="keywordtype">void</span>()&gt; &amp;closeCallback)<span class="keyword"> const </span>{
404
+ <a name="l00387"></a>00387 <span class="keywordtype">int</span> fd, ret;
405
+ <a name="l00388"></a>00388
406
+ <a name="l00389"></a>00389 <span class="keywordflow">do</span> {
407
+ <a name="l00390"></a>00390 fd = socket(PF_UNIX, SOCK_STREAM, 0);
408
+ <a name="l00391"></a>00391 } <span class="keywordflow">while</span> (fd == -1 &amp;&amp; errno == EINTR);
409
+ <a name="l00392"></a>00392 <span class="keywordflow">if</span> (fd == -1) {
410
+ <a name="l00393"></a>00393 <span class="keywordflow">throw</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>(<span class="stringliteral">"Cannot create a new unconnected Unix socket"</span>, errno);
411
+ <a name="l00394"></a>00394 }
412
+ <a name="l00395"></a>00395
413
+ <a name="l00396"></a>00396 <span class="keyword">struct </span>sockaddr_un addr;
414
+ <a name="l00397"></a>00397 addr.sun_family = AF_UNIX;
415
+ <a name="l00398"></a>00398 <span class="keywordflow">if</span> (usingAbstractNamespace) {
416
+ <a name="l00399"></a>00399 strncpy(addr.sun_path + 1, listenSocketName.c_str(), <span class="keyword">sizeof</span>(addr.sun_path) - 1);
417
+ <a name="l00400"></a>00400 addr.sun_path[0] = <span class="charliteral">'\0'</span>;
418
+ <a name="l00401"></a>00401 } <span class="keywordflow">else</span> {
419
+ <a name="l00402"></a>00402 strncpy(addr.sun_path, listenSocketName.c_str(), <span class="keyword">sizeof</span>(addr.sun_path));
420
+ <a name="l00403"></a>00403 }
421
+ <a name="l00404"></a>00404 addr.sun_path[<span class="keyword">sizeof</span>(addr.sun_path) - 1] = <span class="charliteral">'\0'</span>;
422
+ <a name="l00405"></a>00405 <span class="keywordflow">do</span> {
423
+ <a name="l00406"></a>00406 ret =<a class="code" href="classPassenger_1_1Application.html#34636f796ff3924ad5ec142aaa581379" title="Connect to this application instance with the purpose of sending a request to the..."> ::connect</a>(fd, (<span class="keyword">const</span> sockaddr *) &amp;addr, <span class="keyword">sizeof</span>(addr));
424
+ <a name="l00407"></a>00407 } <span class="keywordflow">while</span> (ret == -1 &amp;&amp; errno == EINTR);
425
+ <a name="l00408"></a>00408 <span class="keywordflow">if</span> (ret == -1) {
426
+ <a name="l00409"></a>00409 <span class="keywordtype">int</span> e = errno;
427
+ <a name="l00410"></a>00410 <span class="keywordtype">string</span> message(<span class="stringliteral">"Cannot connect to Unix socket '"</span>);
428
+ <a name="l00411"></a>00411 message.append(listenSocketName);
429
+ <a name="l00412"></a>00412 message.append(<span class="stringliteral">"' on the abstract namespace"</span>);
430
+ <a name="l00413"></a>00413 <span class="keywordflow">throw</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>(message, e);
431
+ <a name="l00414"></a>00414 }
432
+ <a name="l00415"></a>00415
433
+ <a name="l00416"></a>00416 <span class="keywordflow">return</span> <a class="code" href="group__Support.html#g41b6c4a82fed72531a147de0505a8396" title="Convenience shortcut for creating a shared_ptr.">ptr</a>(<span class="keyword">new</span> StandardSession(pid, closeCallback, fd));
434
+ <a name="l00417"></a>00417 }
435
+ <a name="l00418"></a>00418 };
436
+ <a name="l00419"></a>00419 <span class="comment"></span>
437
+ <a name="l00420"></a>00420 <span class="comment">/** Convenient alias for Application smart pointer. */</span>
438
+ <a name="l00421"></a><a class="code" href="namespacePassenger.html#6a15fd5e8765802a0b8b077e15297e18">00421</a> <span class="keyword">typedef</span> shared_ptr&lt;Application&gt; <a class="code" href="namespacePassenger.html#6a15fd5e8765802a0b8b077e15297e18" title="Convenient alias for Application smart pointer.">ApplicationPtr</a>;
439
+ <a name="l00422"></a>00422
440
+ <a name="l00423"></a>00423 } <span class="comment">// namespace Passenger</span>
441
+ <a name="l00424"></a>00424
442
+ <a name="l00425"></a>00425 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_APPLICATION_H_ */</span>
443
+ </pre></div></div>
444
+ <hr size="1"><address style="text-align: right;"><small>Generated on Mon Dec 1 14:27:22 2008 for Passenger by&nbsp;
445
+ <a href="http://www.doxygen.org/index.html">
446
+ <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
447
+ </body>
448
+ </html>