passenger 4.0.27 → 4.0.28

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 (156) hide show
  1. data.tar.gz.asc +7 -7
  2. data/.gitignore +1 -0
  3. data/NEWS +22 -0
  4. data/build/preprocessor.rb +10 -0
  5. data/build/rpm.rb +74 -65
  6. data/debian.template/rules.template +8 -0
  7. data/dev/copy_boost_headers.rb +11 -2
  8. data/doc/Users guide Apache.idmap.txt +161 -145
  9. data/doc/Users guide Apache.txt +12 -1
  10. data/doc/Users guide Nginx.idmap.txt +142 -126
  11. data/doc/Users guide Nginx.txt +14 -1
  12. data/doc/Users guide Standalone.txt +1 -0
  13. data/doc/users_guide_snippets/environment_variables.txt +1 -1
  14. data/doc/users_guide_snippets/installation.txt +2 -0
  15. data/doc/users_guide_snippets/tips.txt +118 -0
  16. data/ext/apache2/Configuration.cpp +0 -6
  17. data/ext/apache2/Configuration.hpp +0 -5
  18. data/ext/apache2/ConfigurationCommands.cpp +7 -0
  19. data/ext/apache2/ConfigurationFields.hpp +2 -0
  20. data/ext/apache2/ConfigurationSetters.cpp +24 -0
  21. data/ext/apache2/CreateDirConfig.cpp +1 -0
  22. data/ext/apache2/Hooks.cpp +0 -1
  23. data/ext/apache2/MergeDirConfig.cpp +7 -0
  24. data/ext/apache2/SetHeaders.cpp +5 -1
  25. data/ext/boost/cregex.hpp +39 -0
  26. data/ext/boost/libs/regex/src/c_regex_traits.cpp +193 -0
  27. data/ext/boost/libs/regex/src/cpp_regex_traits.cpp +117 -0
  28. data/ext/boost/libs/regex/src/cregex.cpp +660 -0
  29. data/ext/boost/libs/regex/src/instances.cpp +32 -0
  30. data/ext/boost/libs/regex/src/internals.hpp +35 -0
  31. data/ext/boost/libs/regex/src/posix_api.cpp +296 -0
  32. data/ext/boost/libs/regex/src/regex.cpp +227 -0
  33. data/ext/boost/libs/regex/src/regex_debug.cpp +59 -0
  34. data/ext/boost/libs/regex/src/regex_raw_buffer.cpp +72 -0
  35. data/ext/boost/libs/regex/src/regex_traits_defaults.cpp +692 -0
  36. data/ext/boost/libs/regex/src/static_mutex.cpp +179 -0
  37. data/ext/boost/libs/regex/src/wc_regex_traits.cpp +301 -0
  38. data/ext/boost/libs/regex/src/wide_posix_api.cpp +315 -0
  39. data/ext/boost/libs/regex/src/winstances.cpp +35 -0
  40. data/ext/boost/regex.h +100 -0
  41. data/ext/boost/regex.hpp +37 -0
  42. data/ext/boost/regex/concepts.hpp +1128 -0
  43. data/ext/boost/regex/config.hpp +435 -0
  44. data/ext/boost/regex/config/borland.hpp +72 -0
  45. data/ext/boost/regex/config/cwchar.hpp +207 -0
  46. data/ext/boost/regex/mfc.hpp +190 -0
  47. data/ext/boost/regex/pattern_except.hpp +100 -0
  48. data/ext/boost/regex/pending/object_cache.hpp +165 -0
  49. data/ext/boost/regex/pending/static_mutex.hpp +179 -0
  50. data/ext/boost/regex/pending/unicode_iterator.hpp +776 -0
  51. data/ext/boost/regex/regex_traits.hpp +35 -0
  52. data/ext/boost/regex/user.hpp +93 -0
  53. data/ext/boost/regex/v4/basic_regex.hpp +782 -0
  54. data/ext/boost/regex/v4/basic_regex_creator.hpp +1571 -0
  55. data/ext/boost/regex/v4/basic_regex_parser.hpp +2874 -0
  56. data/ext/boost/regex/v4/c_regex_traits.hpp +211 -0
  57. data/ext/boost/regex/v4/char_regex_traits.hpp +81 -0
  58. data/ext/boost/regex/v4/cpp_regex_traits.hpp +1099 -0
  59. data/ext/boost/regex/v4/cregex.hpp +330 -0
  60. data/ext/boost/regex/v4/error_type.hpp +59 -0
  61. data/ext/boost/regex/v4/fileiter.hpp +455 -0
  62. data/ext/boost/regex/v4/instances.hpp +222 -0
  63. data/ext/boost/regex/v4/iterator_category.hpp +91 -0
  64. data/ext/boost/regex/v4/iterator_traits.hpp +135 -0
  65. data/ext/boost/regex/v4/match_flags.hpp +138 -0
  66. data/ext/boost/regex/v4/match_results.hpp +702 -0
  67. data/ext/boost/regex/v4/mem_block_cache.hpp +99 -0
  68. data/ext/boost/regex/v4/perl_matcher.hpp +587 -0
  69. data/ext/boost/regex/v4/perl_matcher_common.hpp +996 -0
  70. data/ext/boost/regex/v4/perl_matcher_non_recursive.hpp +1642 -0
  71. data/ext/boost/regex/v4/perl_matcher_recursive.hpp +991 -0
  72. data/ext/boost/regex/v4/primary_transform.hpp +146 -0
  73. data/ext/boost/regex/v4/protected_call.hpp +81 -0
  74. data/ext/boost/regex/v4/regbase.hpp +180 -0
  75. data/ext/boost/regex/v4/regex.hpp +202 -0
  76. data/ext/boost/regex/v4/regex_format.hpp +1156 -0
  77. data/ext/boost/regex/v4/regex_fwd.hpp +73 -0
  78. data/ext/boost/regex/v4/regex_grep.hpp +155 -0
  79. data/ext/boost/regex/v4/regex_iterator.hpp +201 -0
  80. data/ext/boost/regex/v4/regex_match.hpp +382 -0
  81. data/ext/boost/regex/v4/regex_merge.hpp +93 -0
  82. data/ext/boost/regex/v4/regex_raw_buffer.hpp +210 -0
  83. data/ext/boost/regex/v4/regex_replace.hpp +99 -0
  84. data/ext/boost/regex/v4/regex_search.hpp +217 -0
  85. data/ext/boost/regex/v4/regex_split.hpp +172 -0
  86. data/ext/boost/regex/v4/regex_token_iterator.hpp +342 -0
  87. data/ext/boost/regex/v4/regex_traits.hpp +189 -0
  88. data/ext/boost/regex/v4/regex_traits_defaults.hpp +371 -0
  89. data/ext/boost/regex/v4/regex_workaround.hpp +232 -0
  90. data/ext/boost/regex/v4/states.hpp +301 -0
  91. data/ext/boost/regex/v4/sub_match.hpp +512 -0
  92. data/ext/boost/regex/v4/syntax_type.hpp +105 -0
  93. data/ext/boost/regex/v4/u32regex_iterator.hpp +193 -0
  94. data/ext/boost/regex/v4/u32regex_token_iterator.hpp +377 -0
  95. data/ext/boost/regex/v4/w32_regex_traits.hpp +741 -0
  96. data/ext/boost/regex_fwd.hpp +33 -0
  97. data/ext/common/AgentsStarter.h +0 -11
  98. data/ext/common/ApplicationPool2/Common.h +1 -7
  99. data/ext/common/ApplicationPool2/DirectSpawner.h +3 -3
  100. data/ext/common/ApplicationPool2/Group.h +166 -69
  101. data/ext/common/ApplicationPool2/Implementation.cpp +55 -10
  102. data/ext/common/ApplicationPool2/Options.h +45 -10
  103. data/ext/common/ApplicationPool2/PipeWatcher.h +1 -2
  104. data/ext/common/ApplicationPool2/Pool.h +29 -7
  105. data/ext/common/ApplicationPool2/Process.h +22 -3
  106. data/ext/common/ApplicationPool2/Session.h +1 -0
  107. data/ext/common/ApplicationPool2/SmartSpawner.h +5 -10
  108. data/ext/common/ApplicationPool2/Spawner.h +10 -15
  109. data/ext/common/ApplicationPool2/SuperGroup.h +10 -9
  110. data/ext/common/Constants.h +1 -3
  111. data/ext/common/Hooks.h +193 -0
  112. data/ext/common/Logging.cpp +67 -2
  113. data/ext/common/Logging.h +23 -1
  114. data/ext/common/Utils.cpp +0 -21
  115. data/ext/common/Utils.h +0 -42
  116. data/ext/common/Utils/CachedFileStat.hpp +1 -1
  117. data/ext/common/Utils/StrIntUtils.h +61 -14
  118. data/ext/common/Utils/StringMap.h +4 -0
  119. data/ext/common/agents/HelperAgent/AgentOptions.h +4 -4
  120. data/ext/common/agents/HelperAgent/Main.cpp +2 -3
  121. data/ext/common/agents/HelperAgent/RequestHandler.h +65 -2
  122. data/ext/common/agents/LoggingAgent/FilterSupport.h +3 -1
  123. data/ext/common/agents/Watchdog/Main.cpp +8 -72
  124. data/ext/nginx/CacheLocationConfig.c +29 -1
  125. data/ext/nginx/Configuration.c +0 -12
  126. data/ext/nginx/Configuration.h +0 -1
  127. data/ext/nginx/ConfigurationCommands.c +10 -0
  128. data/ext/nginx/ConfigurationFields.h +2 -0
  129. data/ext/nginx/CreateLocationConfig.c +4 -0
  130. data/ext/nginx/MergeLocationConfig.c +6 -0
  131. data/ext/oxt/system_calls.cpp +7 -1
  132. data/ext/oxt/system_calls.hpp +7 -7
  133. data/helper-scripts/node-loader.js +6 -2
  134. data/helper-scripts/rack-loader.rb +5 -2
  135. data/helper-scripts/rack-preloader.rb +5 -2
  136. data/lib/phusion_passenger.rb +1 -1
  137. data/lib/phusion_passenger/apache2/config_options.rb +8 -0
  138. data/lib/phusion_passenger/constants.rb +0 -1
  139. data/lib/phusion_passenger/nginx/config_options.rb +9 -2
  140. data/lib/phusion_passenger/platform_info/apache.rb +2 -1
  141. data/lib/phusion_passenger/platform_info/compiler.rb +15 -1
  142. data/lib/phusion_passenger/platform_info/cxx_portability.rb +2 -0
  143. data/node_lib/phusion_passenger/httplib_emulation.js +85 -17
  144. data/node_lib/phusion_passenger/request_handler.js +10 -2
  145. data/rpm/Vagrantfile +32 -0
  146. data/rpm/get_distro_id.py +4 -0
  147. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +2 -2
  148. data/test/cxx/ApplicationPool2/PoolTest.cpp +60 -9
  149. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +2 -6
  150. data/test/cxx/CachedFileStatTest.cpp +5 -5
  151. data/test/cxx/RequestHandlerTest.cpp +3 -6
  152. data/test/cxx/UtilsTest.cpp +30 -0
  153. data/test/node/httplib_emulation_spec.js +491 -0
  154. data/test/node/spec_helper.js +25 -0
  155. metadata +78 -2
  156. metadata.gz.asc +7 -7
@@ -24,6 +24,7 @@
24
24
  */
25
25
  #include <typeinfo>
26
26
  #include <algorithm>
27
+ #include <utility>
27
28
  #include <boost/make_shared.hpp>
28
29
  #include <boost/date_time/posix_time/posix_time_types.hpp>
29
30
  #include <oxt/backtrace.hpp>
@@ -156,6 +157,23 @@ SuperGroup::generateSecret() const {
156
157
  return getPool()->randomGenerator->generateAsciiString(43);
157
158
  }
158
159
 
160
+ void
161
+ SuperGroup::runInitializationHooks() const {
162
+ getPool()->runHookScripts("after_initialize_supergroup",
163
+ boost::bind(&SuperGroup::setupInitializationOrDestructionHook, this, _1));
164
+ }
165
+
166
+ void
167
+ SuperGroup::runDestructionHooks() const {
168
+ getPool()->runHookScripts("before_destroy_supergroup",
169
+ boost::bind(&SuperGroup::setupInitializationOrDestructionHook, this, _1));
170
+ }
171
+
172
+ void
173
+ SuperGroup::setupInitializationOrDestructionHook(HookScriptOptions &options) const {
174
+ options.environment.push_back(make_pair("PASSENGER_APP_ROOT", this->options.appRoot));
175
+ }
176
+
159
177
  void
160
178
  SuperGroup::createInterruptableThread(const boost::function<void ()> &func, const string &name,
161
179
  unsigned int stackSize)
@@ -216,7 +234,7 @@ SuperGroup::realDoInitialize(const Options &options, unsigned int generation) {
216
234
  const GetWaiter &waiter = getWaitlist.front();
217
235
  actions.push_back(boost::bind(waiter.callback,
218
236
  SessionPtr(), exception));
219
- getWaitlist.pop();
237
+ getWaitlist.pop_front();
220
238
  }
221
239
  } else {
222
240
  for (it = componentInfos.begin(); it != componentInfos.end(); it++) {
@@ -236,9 +254,11 @@ SuperGroup::realDoInitialize(const Options &options, unsigned int generation) {
236
254
  verifyInvariants();
237
255
  P_TRACE(2, "Done initializing SuperGroup " << inspect());
238
256
  }
257
+
239
258
  this_thread::disable_interruption di;
240
259
  this_thread::disable_syscall_interruption dsi;
241
260
  runAllActions(actions);
261
+ runInitializationHooks();
242
262
  }
243
263
 
244
264
  void
@@ -861,7 +881,8 @@ Group::spawnThreadRealMain(const SpawnerPtr &spawner, const Options &options, un
861
881
  m_spawning = false;
862
882
 
863
883
  done = done
864
- || ((unsigned long) getProcessCount() >= options.minProcesses && getWaitlist.empty())
884
+ || (getProcessCount() >= options.minProcesses && getWaitlist.empty())
885
+ || (options.maxProcesses != 0 && getProcessCount() >= options.maxProcesses)
865
886
  || pool->atFullCapacity(false);
866
887
  m_spawning = !done;
867
888
  if (done) {
@@ -899,7 +920,9 @@ Group::shouldSpawnForGetAction() const {
899
920
 
900
921
  bool
901
922
  Group::allowSpawn() const {
902
- return isAlive() && !poolAtFullCapacity();
923
+ return isAlive()
924
+ && !poolAtFullCapacity()
925
+ && (options.maxProcesses == 0 || getProcessCount() < options.maxProcesses);
903
926
  }
904
927
 
905
928
  void
@@ -1154,6 +1177,26 @@ Group::getResourceLocator() const {
1154
1177
  return getPool()->spawnerFactory->getResourceLocator();
1155
1178
  }
1156
1179
 
1180
+ // 'process' is not a reference so that bind(runAttachHooks, ...) causes the shared
1181
+ // pointer reference to increment.
1182
+ void
1183
+ Group::runAttachHooks(const ProcessPtr process) const {
1184
+ getPool()->runHookScripts("attached_process",
1185
+ boost::bind(&Group::setupAttachOrDetachHook, this, process, _1));
1186
+ }
1187
+
1188
+ void
1189
+ Group::runDetachHooks(const ProcessPtr process) const {
1190
+ getPool()->runHookScripts("detached_process",
1191
+ boost::bind(&Group::setupAttachOrDetachHook, this, process, _1));
1192
+ }
1193
+
1194
+ void
1195
+ Group::setupAttachOrDetachHook(const ProcessPtr process, HookScriptOptions &options) const {
1196
+ options.environment.push_back(make_pair("PASSENGER_PROCESS_PID", toString(process->pid)));
1197
+ options.environment.push_back(make_pair("PASSENGER_APP_ROOT", this->options.appRoot));
1198
+ }
1199
+
1157
1200
  string
1158
1201
  Group::generateSecret(const SuperGroupPtr &superGroup) {
1159
1202
  return superGroup->getPool()->randomGenerator->generateAsciiString(43);
@@ -1196,6 +1239,11 @@ Session::getGupid() const {
1196
1239
  return getProcess()->gupid;
1197
1240
  }
1198
1241
 
1242
+ int
1243
+ Session::getStickySessionId() const {
1244
+ return getProcess()->stickySessionId;
1245
+ }
1246
+
1199
1247
  const GroupPtr
1200
1248
  Session::getGroup() const {
1201
1249
  return getProcess()->getGroup();
@@ -1216,11 +1264,10 @@ Session::kill(int signo) {
1216
1264
 
1217
1265
  PipeWatcher::DataCallback PipeWatcher::onData;
1218
1266
 
1219
- PipeWatcher::PipeWatcher(const FileDescriptor &_fd, const char *_name, pid_t _pid, bool _print)
1267
+ PipeWatcher::PipeWatcher(const FileDescriptor &_fd, const char *_name, pid_t _pid)
1220
1268
  : fd(_fd),
1221
1269
  name(_name),
1222
- pid(_pid),
1223
- print(_print)
1270
+ pid(_pid)
1224
1271
  {
1225
1272
  started = false;
1226
1273
  }
@@ -1276,8 +1323,7 @@ PipeWatcher::threadMain() {
1276
1323
  }
1277
1324
  } else if (ret == 1 && buf[0] == '\n') {
1278
1325
  UPDATE_TRACE_POINT();
1279
- P_LOG(print ? LVL_INFO : LVL_DEBUG,
1280
- "[App " << pid << " " << name << "] ");
1326
+ printAppOutput(pid, name, "", 0);
1281
1327
  } else {
1282
1328
  UPDATE_TRACE_POINT();
1283
1329
  vector<StaticString> lines;
@@ -1287,8 +1333,7 @@ PipeWatcher::threadMain() {
1287
1333
  }
1288
1334
  split(StaticString(buf, ret2), '\n', lines);
1289
1335
  foreach (const StaticString line, lines) {
1290
- P_LOG(print ? LVL_INFO : LVL_DEBUG,
1291
- "[App " << pid << " " << name << "] " << line);
1336
+ printAppOutput(pid, name, line.data(), line.size());
1292
1337
  }
1293
1338
  }
1294
1339
 
@@ -146,7 +146,10 @@ private:
146
146
  }
147
147
 
148
148
  public:
149
- /*********** Spawn options that should be set manually ***********/
149
+ /*********** Spawn options that should be set manually ***********
150
+ * These are the options that are relevant while spawning an application
151
+ * process. These options are only used during spawning.
152
+ */
150
153
 
151
154
  /**
152
155
  * The root directory of the application to spawn. In case of a Ruby on Rails
@@ -294,13 +297,25 @@ public:
294
297
  bool raiseInternalError;
295
298
 
296
299
 
297
- /*********** Per-group pool options that should be set manually ***********/
300
+ /*********** Per-group pool options that should be set manually ***********
301
+ * These options dictate how Pool will manage processes, routing, etc. within
302
+ * a single Group. These options are not process-specific, only group-specific.
303
+ */
298
304
 
299
305
  /**
300
306
  * The minimum number of processes for the current group that the application
301
307
  * pool's cleaner thread should keep around.
302
308
  */
303
- unsigned long minProcesses;
309
+ unsigned int minProcesses;
310
+
311
+ /**
312
+ * The maximum number of processes that may be spawned
313
+ * for this app root. This option only has effect if it's lower than
314
+ * the pool size.
315
+ *
316
+ * A value of 0 means unspecified, and has no effect.
317
+ */
318
+ unsigned int maxProcesses;
304
319
 
305
320
  /** The number of seconds that preloader processes may stay alive idling. */
306
321
  long maxPreloaderIdleTime;
@@ -317,10 +332,23 @@ public:
317
332
  */
318
333
  unsigned int maxRequestQueueSize;
319
334
 
335
+ /**
336
+ * The Union Station key to use in case analytics logging is enabled.
337
+ * It is used by Pool::collectAnalytics() and other administrative
338
+ * functions which are called periodically. Because they do not belong
339
+ * to any request, and they may still want to log to Union Station,
340
+ * this key is stored in the per-group options structure.
341
+ *
342
+ * It is not used on a per-request basis. Per-request analytics logging
343
+ * (and Union Station logging) uses the logger object in the `logger` field
344
+ * instead.
345
+ */
346
+ StaticString unionStationKey;
347
+
320
348
  /*-----------------*/
321
349
 
322
350
 
323
- /*********** Per-request options that should be set manually and that only matter to Pool ***********/
351
+ /*********** Per-request options that should be set manually ***********/
324
352
 
325
353
  /** Current request host name. */
326
354
  StaticString hostName;
@@ -335,9 +363,9 @@ public:
335
363
  UnionStation::LoggerPtr logger;
336
364
 
337
365
  /**
338
- * The Union Station key to use in case analytics logging is enabled.
366
+ * A sticky session ID for routing to a specific process.
339
367
  */
340
- StaticString unionStationKey;
368
+ unsigned int stickySessionId;
341
369
 
342
370
  /**
343
371
  * A throttling rate for file stats. When set to a non-zero value N,
@@ -372,7 +400,10 @@ public:
372
400
  /*-----------------*/
373
401
 
374
402
 
375
- /*********** Spawn options automatically set by Pool ***********/
403
+ /*********** Spawn options automatically set by Pool ***********
404
+ * These options are passed to the Spawner. The Pool::get() caller may not
405
+ * see these values.
406
+ */
376
407
 
377
408
  /** The secret key of the pool group that the spawned process is to belong to. */
378
409
  StaticString groupSecret;
@@ -401,10 +432,12 @@ public:
401
432
  raiseInternalError = false;
402
433
 
403
434
  minProcesses = 1;
435
+ maxProcesses = 0;
404
436
  maxPreloaderIdleTime = -1;
405
437
  maxOutOfBandWorkInstances = 1;
406
438
  maxRequestQueueSize = 100;
407
439
 
440
+ stickySessionId = 0;
408
441
  statThrottleRate = 0;
409
442
  maxRequests = 0;
410
443
  noop = false;
@@ -494,8 +527,9 @@ public:
494
527
  }
495
528
 
496
529
  Options &clearPerRequestFields() {
497
- hostName = string();
498
- uri = string();
530
+ hostName = StaticString();
531
+ uri = StaticString();
532
+ stickySessionId = 0;
499
533
  noop = false;
500
534
  return clearLogger();
501
535
  }
@@ -546,14 +580,15 @@ public:
546
580
  appendKeyValue (vec, "logging_agent_password", loggingAgentPassword);
547
581
  appendKeyValue4(vec, "debugger", debugger);
548
582
  appendKeyValue4(vec, "analytics", analytics);
549
- appendKeyValue (vec, "union_station_key", unionStationKey);
550
583
 
551
584
  appendKeyValue (vec, "group_secret", groupSecret);
552
585
  }
553
586
  if (fields & PER_GROUP_POOL_OPTIONS) {
554
587
  appendKeyValue3(vec, "min_processes", minProcesses);
588
+ appendKeyValue3(vec, "max_processes", maxProcesses);
555
589
  appendKeyValue2(vec, "max_preloader_idle_time", maxPreloaderIdleTime);
556
590
  appendKeyValue3(vec, "max_out_of_band_work_instances", maxOutOfBandWorkInstances);
591
+ appendKeyValue (vec, "union_station_key", unionStationKey);
557
592
  }
558
593
 
559
594
  /*********************************/
@@ -47,12 +47,11 @@ struct PipeWatcher: public boost::enable_shared_from_this<PipeWatcher> {
47
47
  FileDescriptor fd;
48
48
  const char *name;
49
49
  pid_t pid;
50
- bool print;
51
50
  bool started;
52
51
  boost::mutex startSyncher;
53
52
  boost::condition_variable startCond;
54
53
 
55
- PipeWatcher(const FileDescriptor &_fd, const char *name, pid_t pid, bool _print);
54
+ PipeWatcher(const FileDescriptor &_fd, const char *name, pid_t pid);
56
55
  void initialize();
57
56
  void start();
58
57
  static void threadMain(boost::shared_ptr<PipeWatcher> self);
@@ -48,9 +48,9 @@
48
48
  #include <ApplicationPool2/Options.h>
49
49
  #include <UnionStation.h>
50
50
  #include <Logging.h>
51
- #include <SafeLibev.h>
52
51
  #include <Exceptions.h>
53
52
  #include <RandomGenerator.h>
53
+ #include <Hooks.h>
54
54
  #include <Utils/Lock.h>
55
55
  #include <Utils/AnsiColorConstants.h>
56
56
  #include <Utils/SystemTime.h>
@@ -129,7 +129,6 @@ public:
129
129
  RandomGeneratorPtr randomGenerator;
130
130
 
131
131
  mutable boost::mutex syncher;
132
- SafeLibev *libev;
133
132
  unsigned int max;
134
133
  unsigned long long maxIdleTime;
135
134
 
@@ -193,6 +192,7 @@ public:
193
192
  */
194
193
  vector<GetWaiter> getWaitlist;
195
194
 
195
+ const VariantMap *agentsOptions;
196
196
  DebugSupportPtr debugSupport;
197
197
 
198
198
  static void runAllActions(const vector<Callback> &actions) {
@@ -247,6 +247,27 @@ public:
247
247
  }
248
248
  }
249
249
 
250
+ bool runHookScripts(const char *name,
251
+ const boost::function<void (HookScriptOptions &)> &setup) const
252
+ {
253
+ if (agentsOptions != NULL) {
254
+ string hookName = string("hook_") + name;
255
+ string spec = agentsOptions->get(hookName, false);
256
+ if (!spec.empty()) {
257
+ HookScriptOptions options;
258
+ options.agentsOptions = agentsOptions;
259
+ options.name = name;
260
+ options.spec = spec;
261
+ setup(options);
262
+ return Passenger::runHookScripts(options);
263
+ } else {
264
+ return true;
265
+ }
266
+ } else {
267
+ return true;
268
+ }
269
+ }
270
+
250
271
  ProcessPtr findOldestIdleProcess() const {
251
272
  ProcessPtr oldestIdleProcess;
252
273
 
@@ -343,7 +364,7 @@ public:
343
364
  postLockActions.push_back(boost::bind(
344
365
  getWaitlist.front().callback, SessionPtr(),
345
366
  exception));
346
- getWaitlist.pop();
367
+ getWaitlist.pop_front();
347
368
  }
348
369
  }
349
370
 
@@ -385,7 +406,7 @@ public:
385
406
  getWaitlist.reserve(getWaitlist.size() + superGroup->getWaitlist.size());
386
407
  while (!superGroup->getWaitlist.empty()) {
387
408
  getWaitlist.push_back(superGroup->getWaitlist.front());
388
- superGroup->getWaitlist.pop();
409
+ superGroup->getWaitlist.pop_front();
389
410
  }
390
411
  }
391
412
 
@@ -861,11 +882,11 @@ public:
861
882
  const SuperGroupPtr getSuperGroup(const char *name);
862
883
 
863
884
  public:
864
- Pool(SafeLibev *libev, const SpawnerFactoryPtr &spawnerFactory,
885
+ Pool(const SpawnerFactoryPtr &spawnerFactory,
865
886
  const LoggerFactoryPtr &loggerFactory = LoggerFactoryPtr(),
866
- const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr())
887
+ const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr(),
888
+ const VariantMap *agentsOptions = NULL)
867
889
  {
868
- this->libev = libev;
869
890
  this->spawnerFactory = spawnerFactory;
870
891
  this->loggerFactory = loggerFactory;
871
892
  if (randomGenerator != NULL) {
@@ -873,6 +894,7 @@ public:
873
894
  } else {
874
895
  this->randomGenerator = boost::make_shared<RandomGenerator>();
875
896
  }
897
+ this->agentsOptions = agentsOptions;
876
898
 
877
899
  lifeStatus = ALIVE;
878
900
  max = 6;
@@ -209,7 +209,11 @@ public:
209
209
  SafeLibev * const libev;
210
210
  /** Process PID. */
211
211
  pid_t pid;
212
- /** UUID for this process, randomly generated and will never appear again. */
212
+ /** An ID that uniquely identifies this Process in the Group, for
213
+ * use in implementing sticky sessions. Set by Group::attach(). */
214
+ unsigned int stickySessionId;
215
+ /** UUID for this process, randomly generated and extremely unlikely to ever
216
+ * appear again in this universe. */
213
217
  string gupid;
214
218
  string connectPassword;
215
219
  /** Admin socket, see class description. */
@@ -326,6 +330,7 @@ public:
326
330
  : pqHandle(NULL),
327
331
  libev(_libev.get()),
328
332
  pid(_pid),
333
+ stickySessionId(0),
329
334
  gupid(_gupid),
330
335
  connectPassword(_connectPassword),
331
336
  adminSocket(_adminSocket),
@@ -352,13 +357,13 @@ public:
352
357
 
353
358
  if (_adminSocket != -1) {
354
359
  PipeWatcherPtr watcher = boost::make_shared<PipeWatcher>(_adminSocket,
355
- "stdout", pid, config->forwardStdout);
360
+ "stdout", pid);
356
361
  watcher->initialize();
357
362
  watcher->start();
358
363
  }
359
364
  if (_errorPipe != -1) {
360
365
  PipeWatcherPtr watcher = boost::make_shared<PipeWatcher>(_errorPipe,
361
- "stderr", pid, config->forwardStderr);
366
+ "stderr", pid);
362
367
  watcher->initialize();
363
368
  watcher->start();
364
369
  }
@@ -537,9 +542,22 @@ public:
537
542
  return atFullUtilization();
538
543
  }
539
544
 
545
+ /**
546
+ * Whether we've reached the maximum number of concurrent sessions for this
547
+ * process.
548
+ */
540
549
  bool atFullUtilization() const {
541
550
  return concurrency != 0 && sessions >= concurrency;
542
551
  }
552
+
553
+ /**
554
+ * Whether a get() request can be routed to this process, assuming that
555
+ * the sticky session ID (if any) matches. This is only not the case
556
+ * if this process is at full utilization.
557
+ */
558
+ bool canBeRoutedTo() const {
559
+ return !atFullUtilization();
560
+ }
543
561
 
544
562
  /**
545
563
  * Create a new communication session with this process. This will connect to one
@@ -588,6 +606,7 @@ public:
588
606
  template<typename Stream>
589
607
  void inspectXml(Stream &stream, bool includeSockets = true) const {
590
608
  stream << "<pid>" << pid << "</pid>";
609
+ stream << "<sticky_session_id>" << stickySessionId << "</sticky_session_id>";
591
610
  stream << "<gupid>" << gupid << "</gupid>";
592
611
  stream << "<connect_password>" << connectPassword << "</connect_password>";
593
612
  stream << "<concurrency>" << concurrency << "</concurrency>";
@@ -108,6 +108,7 @@ public:
108
108
  const string &getConnectPassword() const;
109
109
  pid_t getPid() const;
110
110
  const string &getGupid() const;
111
+ int getStickySessionId() const;
111
112
  const GroupPtr getGroup() const;
112
113
  void requestOOBW();
113
114
  int kill(int signo);