passenger 5.1.7 → 5.1.8

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +13 -2
  3. data/CONTRIBUTING.md +1 -1
  4. data/build/agent.rb +1 -1
  5. data/build/cxx_tests.rb +6 -0
  6. data/build/support/cxx_dependency_map.rb +1286 -391
  7. data/build/support/general.rb +0 -26
  8. data/resources/templates/standalone/rails_asset_pipeline.erb +2 -2
  9. data/src/agent/Core/ApiServer.h +49 -44
  10. data/src/agent/Core/ApplicationPool/Pool.h +1 -1
  11. data/src/agent/Core/ApplicationPool/Process.h +1 -1
  12. data/src/agent/Core/ApplicationPool/Socket.h +1 -1
  13. data/src/agent/Core/Controller.h +16 -8
  14. data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
  15. data/src/agent/Core/Controller/Config.cpp +68 -0
  16. data/src/agent/Core/Controller/Config.h +70 -34
  17. data/src/agent/Core/Controller/ForwardResponse.cpp +5 -5
  18. data/src/agent/Core/Controller/Hooks.cpp +5 -14
  19. data/src/agent/Core/Controller/Implementation.cpp +1 -1
  20. data/src/agent/Core/Controller/InitRequest.cpp +31 -29
  21. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +4 -4
  22. data/src/agent/Core/Controller/InternalUtils.cpp +3 -3
  23. data/src/agent/Core/Controller/Miscellaneous.cpp +1 -1
  24. data/src/agent/Core/Controller/Request.h +2 -2
  25. data/src/agent/Core/Controller/SendRequest.cpp +5 -5
  26. data/src/agent/Core/Controller/StateInspection.cpp +1 -1
  27. data/src/agent/Core/Controller/TurboCaching.h +2 -2
  28. data/src/agent/Core/CoreMain.cpp +2 -2
  29. data/src/agent/Core/ResponseCache.h +3 -3
  30. data/src/agent/Core/SpawningKit/BackgroundIOCapturer.h +3 -3
  31. data/src/agent/Core/SpawningKit/DirectSpawner.h +2 -2
  32. data/src/agent/Core/SpawningKit/PipeWatcher.h +3 -3
  33. data/src/agent/Core/SpawningKit/SmartSpawner.h +2 -2
  34. data/src/agent/Core/SpawningKit/Spawner.h +1 -1
  35. data/src/agent/Core/UnionStation/Connection.h +1 -1
  36. data/src/agent/Core/UnionStation/Context.h +1 -1
  37. data/src/agent/Core/UnionStation/Transaction.h +1 -1
  38. data/src/agent/Shared/ApiServerUtils.h +73 -27
  39. data/src/agent/Shared/Base.cpp +61 -73
  40. data/src/agent/UstRouter/ApiServer.h +34 -45
  41. data/src/agent/UstRouter/Controller.h +86 -60
  42. data/src/agent/UstRouter/RemoteSender.h +1 -1
  43. data/src/agent/UstRouter/RemoteSink.h +1 -1
  44. data/src/agent/Watchdog/ApiServer.h +42 -50
  45. data/src/agent/Watchdog/WatchdogMain.cpp +1 -1
  46. data/src/apache2_module/Configuration.hpp +1 -1
  47. data/src/apache2_module/Hooks.cpp +27 -13
  48. data/src/cxx_supportlib/AppTypes.h +1 -1
  49. data/src/cxx_supportlib/BackgroundEventLoop.cpp +1 -1
  50. data/src/cxx_supportlib/ConfigKit/AsyncUtils.h +86 -0
  51. data/src/cxx_supportlib/ConfigKit/Common.h +6 -3
  52. data/src/cxx_supportlib/ConfigKit/IN_PRACTICE.md +1039 -0
  53. data/src/cxx_supportlib/ConfigKit/README.md +112 -497
  54. data/src/cxx_supportlib/ConfigKit/Schema.h +78 -15
  55. data/src/cxx_supportlib/ConfigKit/Store.h +272 -53
  56. data/src/cxx_supportlib/ConfigKit/SubComponentUtils.h +59 -0
  57. data/src/cxx_supportlib/ConfigKit/Utils.h +26 -65
  58. data/src/cxx_supportlib/ConfigKit/ValidationUtils.h +69 -0
  59. data/src/cxx_supportlib/ConfigKit/VariantMapUtils.h +7 -4
  60. data/src/cxx_supportlib/Constants.h +4 -1
  61. data/src/cxx_supportlib/Crypto.cpp +1 -1
  62. data/src/cxx_supportlib/DataStructures/StringKeyTable.h +26 -7
  63. data/src/cxx_supportlib/FileDescriptor.h +1 -1
  64. data/src/cxx_supportlib/Hooks.h +1 -1
  65. data/src/cxx_supportlib/LoggingKit/Assert.h +130 -0
  66. data/src/cxx_supportlib/LoggingKit/Config.h +97 -0
  67. data/src/cxx_supportlib/LoggingKit/Context.h +94 -0
  68. data/src/cxx_supportlib/LoggingKit/Forward.h +95 -0
  69. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +695 -0
  70. data/src/cxx_supportlib/LoggingKit/Logging.h +204 -0
  71. data/src/cxx_supportlib/LoggingKit/LoggingKit.h +33 -0
  72. data/src/cxx_supportlib/LveLoggingDecorator.h +1 -1
  73. data/src/cxx_supportlib/MemoryKit/mbuf.cpp +1 -1
  74. data/src/cxx_supportlib/RandomGenerator.h +1 -1
  75. data/src/cxx_supportlib/SafeLibev.h +1 -1
  76. data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +1 -1
  77. data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
  78. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
  79. data/src/cxx_supportlib/ServerKit/FileBufferedFdSinkChannel.h +1 -1
  80. data/src/cxx_supportlib/ServerKit/HttpChunkedBodyParser.h +1 -1
  81. data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +1 -1
  82. data/src/cxx_supportlib/ServerKit/HttpServer.h +48 -15
  83. data/src/cxx_supportlib/ServerKit/Server.h +79 -52
  84. data/src/cxx_supportlib/StaticString.h +12 -0
  85. data/src/cxx_supportlib/Utils/Curl.h +16 -0
  86. data/src/cxx_supportlib/Utils/FastStringStream.h +6 -1
  87. data/src/cxx_supportlib/Utils/ScopeGuard.h +1 -1
  88. data/src/cxx_supportlib/Utils/StrIntUtils.cpp +2 -19
  89. data/src/cxx_supportlib/WatchdogLauncher.h +3 -2
  90. data/src/ruby_supportlib/phusion_passenger.rb +3 -3
  91. data/src/ruby_supportlib/phusion_passenger/common_library.rb +12 -12
  92. data/src/ruby_supportlib/phusion_passenger/constants.rb +6 -3
  93. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +1 -0
  94. data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +1 -0
  95. metadata +14 -4
  96. data/src/cxx_supportlib/Logging.cpp +0 -295
  97. data/src/cxx_supportlib/Logging.h +0 -385
@@ -22,32 +22,6 @@
22
22
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
23
  # THE SOFTWARE.
24
24
 
25
- class TemplateRenderer
26
- def initialize(filename)
27
- require 'erb' if !defined?(ERB)
28
- @erb = ERB.new(File.read(filename), nil, "-")
29
- @erb.filename = filename
30
- end
31
-
32
- def render
33
- return @erb.result(binding)
34
- end
35
-
36
- def render_to(filename)
37
- puts "Creating #{filename}"
38
- text = render
39
- # When packaging, some timestamps may be modified. The user may not
40
- # have write access to the source root (for example, when Passenger
41
- # Standalone is compiling its runtime), so we only write to the file
42
- # when necessary.
43
- if !File.exist?(filename) || File.writable?(filename) || File.read(filename) != text
44
- File.open(filename, 'w') do |f|
45
- f.write(text)
46
- end
47
- end
48
- end
49
- end
50
-
51
25
  class CxxCodeTemplateRenderer
52
26
  def initialize(filename)
53
27
  if !defined?(CxxCodeBuilder)
@@ -1,5 +1,5 @@
1
- # Rails asset pipeline support.
2
- location ~ "^/assets/.+-([0-9a-f]{32}|[0-9a-f]{64})\..+" {
1
+ # Rails asset pipeline & webpacker support.
2
+ location ~ "^/(assets|packs)/.+-([0-9a-f]{32}|[0-9a-f]{64}|[0-9a-f]{20})\..+" {
3
3
  error_page 490 = @static_asset;
4
4
  error_page 491 = @dynamic_request;
5
5
  recursive_error_pages on;
@@ -28,9 +28,9 @@
28
28
 
29
29
  #include <boost/regex.hpp>
30
30
  #include <oxt/thread.hpp>
31
- #include <sstream>
32
31
  #include <string>
33
32
  #include <cstring>
33
+ #include <exception>
34
34
  #include <sys/types.h>
35
35
 
36
36
  #include <jsoncpp/json.h>
@@ -43,7 +43,8 @@
43
43
  #include <DataStructures/LString.h>
44
44
  #include <Exceptions.h>
45
45
  #include <StaticString.h>
46
- #include <Logging.h>
46
+ #include <LoggingKit/LoggingKit.h>
47
+ #include <LoggingKit/Context.h>
47
48
  #include <Constants.h>
48
49
  #include <Utils/StrIntUtils.h>
49
50
  #include <Utils/BufferedIO.h>
@@ -413,7 +414,7 @@ private:
413
414
  count = mbuf_pool_compact(&ctx->mbuf_pool);
414
415
  SKS_NOTICE_FROM_STATIC(controller, "Freed " << count << " mbufs");
415
416
 
416
- controller->compact(LVL_NOTICE);
417
+ controller->compact(LoggingKit::NOTICE);
417
418
  }
418
419
 
419
420
  void processGc(Client *client, Request *req) {
@@ -475,16 +476,18 @@ private:
475
476
  }
476
477
 
477
478
  HeaderTable headers;
478
- string logFile = getLogFile();
479
- string fileDescriptorLogFile = getFileDescriptorLogFile();
479
+ ConfigKit::Store loggingConfig = LoggingKit::context->getConfig();
480
480
 
481
481
  headers.insert(req->pool, "Content-Type", "application/json");
482
- config["log_level"] = getLogLevel();
483
- if (!logFile.empty()) {
484
- config["log_file"] = logFile;
482
+ config["log_level"] = (int) LoggingKit::parseLevel(loggingConfig["level"].asString());
483
+ if (loggingConfig["target"].isMember("path")) {
484
+ config["log_file"] = loggingConfig["target"]["path"].asString();
485
485
  }
486
- if (!fileDescriptorLogFile.empty()) {
487
- config["file_descriptor_log_file"] = fileDescriptorLogFile;
486
+ if (!loggingConfig["file_descriptor_log_target"].isNull()
487
+ && loggingConfig["file_descriptor_log_target"].isMember("path"))
488
+ {
489
+ config["file_descriptor_log_file"] =
490
+ loggingConfig["file_descriptor_log_target"]["path"].asString();
488
491
  }
489
492
 
490
493
  writeSimpleResponse(client, 200, &headers,
@@ -499,7 +502,11 @@ private:
499
502
 
500
503
  static void configureController(Controller *controller, Json::Value updates) {
501
504
  vector<ConfigKit::Error> errors;
502
- if (!controller->configure(updates, errors)) {
505
+ ControllerConfigChangeRequest req;
506
+
507
+ if (controller->prepareConfigChange(updates, errors, req)) {
508
+ controller->commitConfigChange(req);
509
+ } else {
503
510
  P_ERROR("Unable to apply configuration change to Core controller.\n"
504
511
  "Configuration: " << updates.toStyledString() << "\n"
505
512
  "Errors: " << toString(errors));
@@ -508,46 +515,44 @@ private:
508
515
 
509
516
  void processConfigBody(Client *client, Request *req) {
510
517
  HeaderTable headers;
511
- Json::Value &json = req->jsonBody;
518
+ LoggingKit::ConfigChangeRequest configReq;
519
+ const Json::Value &json = req->jsonBody;
520
+ vector<ConfigKit::Error> errors;
521
+ bool ok;
512
522
 
513
523
  headers.insert(req->pool, "Content-Type", "application/json");
514
524
  headers.insert(req->pool, "Cache-Control", "no-cache, no-store, must-revalidate");
515
525
 
516
- if (json.isMember("log_level")) {
517
- setLogLevel(json["log_level"].asInt());
518
- }
519
- if (json.isMember("log_file")) {
520
- string logFile = json["log_file"].asString();
521
- try {
522
- logFile = absolutizePath(logFile);
523
- } catch (const SystemException &e) {
524
- unsigned int bufsize = 1024;
525
- char *message = (char *) psg_pnalloc(req->pool, bufsize);
526
- snprintf(message, bufsize, "{ \"status\": \"error\", "
527
- "\"message\": \"Cannot absolutize log file filename: %s\" }",
528
- e.what());
529
- writeSimpleResponse(client, 500, &headers, message);
530
- if (!req->ended()) {
531
- endRequest(&client, &req);
532
- }
533
- return;
526
+ try {
527
+ ok = LoggingKit::context->prepareConfigChange(json,
528
+ errors, configReq);
529
+ } catch (const std::exception &e) {
530
+ unsigned int bufsize = 2048;
531
+ char *message = (char *) psg_pnalloc(req->pool, bufsize);
532
+ snprintf(message, bufsize, "{ \"status\": \"error\", "
533
+ "\"message\": \"Error reconfiguring logging system: %s\" }",
534
+ e.what());
535
+ writeSimpleResponse(client, 500, &headers, message);
536
+ if (!req->ended()) {
537
+ endRequest(&client, &req);
534
538
  }
535
-
536
- int e;
537
- if (!setLogFile(logFile, &e)) {
538
- unsigned int bufsize = 1024;
539
- char *message = (char *) psg_pnalloc(req->pool, bufsize);
540
- snprintf(message, bufsize, "{ \"status\": \"error\", "
541
- "\"message\": \"Cannot open log file: %s (errno=%d)\" }",
542
- strerror(e), e);
543
- writeSimpleResponse(client, 500, &headers, message);
544
- if (!req->ended()) {
545
- endRequest(&client, &req);
546
- }
547
- return;
539
+ return;
540
+ }
541
+ if (!ok) {
542
+ unsigned int bufsize = 2048;
543
+ char *message = (char *) psg_pnalloc(req->pool, bufsize);
544
+ snprintf(message, bufsize, "{ \"status\": \"error\", "
545
+ "\"message\": \"Error reconfiguring logging system: %s\" }",
546
+ ConfigKit::toString(errors).c_str());
547
+ writeSimpleResponse(client, 500, &headers, message);
548
+ if (!req->ended()) {
549
+ endRequest(&client, &req);
548
550
  }
549
- P_NOTICE("Log file opened.");
551
+ return;
550
552
  }
553
+
554
+ LoggingKit::context->commitConfigChange(configReq);
555
+
551
556
  for (unsigned int i = 0; i < controllers.size(); i++) {
552
557
  controllers[i]->getContext()->libev->runLater(boost::bind(
553
558
  configureController, controllers[i], json));
@@ -48,7 +48,7 @@
48
48
  #include <oxt/backtrace.hpp>
49
49
  #include <sys/types.h>
50
50
  #include <MemoryKit/palloc.h>
51
- #include <Logging.h>
51
+ #include <LoggingKit/LoggingKit.h>
52
52
  #include <Exceptions.h>
53
53
  #include <Hooks.h>
54
54
  #include <Utils/Lock.h>
@@ -42,7 +42,7 @@
42
42
  #include <cstring>
43
43
  #include <Constants.h>
44
44
  #include <FileDescriptor.h>
45
- #include <Logging.h>
45
+ #include <LoggingKit/LoggingKit.h>
46
46
  #include <Utils/SystemTime.h>
47
47
  #include <Utils/StrIntUtils.h>
48
48
  #include <Utils/Lock.h>
@@ -34,7 +34,7 @@
34
34
  #include <climits>
35
35
  #include <cassert>
36
36
  #include <SmallVector.h>
37
- #include <Logging.h>
37
+ #include <LoggingKit/LoggingKit.h>
38
38
  #include <StaticString.h>
39
39
  #include <MemoryKit/palloc.h>
40
40
  #include <Utils/IOUtils.h>
@@ -32,7 +32,7 @@
32
32
 
33
33
  #define CC_BENCHMARK_POINT(client, req, value) \
34
34
  do { \
35
- if (OXT_UNLIKELY(mainConfigCache.benchmarkMode == value)) { \
35
+ if (OXT_UNLIKELY(mainConfig.benchmarkMode == value)) { \
36
36
  writeBenchmarkResponse(&client, &req); \
37
37
  return; \
38
38
  } \
@@ -61,7 +61,7 @@
61
61
  #include <cassert>
62
62
  #include <cctype>
63
63
 
64
- #include <Logging.h>
64
+ #include <LoggingKit/LoggingKit.h>
65
65
  #include <MessageReadersWriters.h>
66
66
  #include <Constants.h>
67
67
  #include <ConfigKit/ConfigKit.h>
@@ -109,13 +109,14 @@ private:
109
109
  typedef ServerKit::FdSourceChannel FdSourceChannel;
110
110
  typedef ServerKit::FileBufferedChannel FileBufferedChannel;
111
111
  typedef ServerKit::FileBufferedFdSinkChannel FileBufferedFdSinkChannel;
112
+ typedef ControllerConfigChangeRequest ConfigChangeRequest;
112
113
 
113
114
  // If you change this value, make sure that Request::sessionCheckoutTry
114
115
  // has enough bits.
115
116
  static const unsigned int MAX_SESSION_CHECKOUT_TRY = 10;
116
117
 
117
- ControllerMainConfigCache mainConfigCache;
118
- ControllerRequestConfigCachePtr requestConfigCache;
118
+ ControllerMainConfig mainConfig;
119
+ ControllerRequestConfigPtr requestConfig;
119
120
  StringKeyTable< boost::shared_ptr<Options> > poolOptionsCache;
120
121
 
121
122
  HashedStaticString PASSENGER_APP_GROUP_NAME;
@@ -158,8 +159,8 @@ private:
158
159
  void initializeFlags(Client *client, Request *req, RequestAnalysis &analysis);
159
160
  bool respondFromTurboCache(Client *client, Request *req);
160
161
  void initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis);
161
- void fillPoolOptionsFromConfigCaches(Options &options,
162
- const ControllerRequestConfigCachePtr &requestConfigCache);
162
+ void fillPoolOptionsFromConfigCaches(Options &options, psg_pool_t *pool,
163
+ const ControllerRequestConfigPtr &requestConfigCache);
163
164
  static void fillPoolOption(Request *req, StaticString &field,
164
165
  const HashedStaticString &name);
165
166
  static void fillPoolOption(Request *req, int &field,
@@ -350,7 +351,6 @@ protected:
350
351
  virtual void onNextRequestEarlyReadError(Client *client, Request *req, int errcode);
351
352
  virtual bool shouldDisconnectClientOnShutdown(Client *client);
352
353
  virtual bool supportsUpgrade(Client *client, Request *req);
353
- virtual void onConfigChange(const ConfigKit::Store *oldConfig);
354
354
 
355
355
 
356
356
  /****** Marked virtual so that unit tests can mock these ******/
@@ -380,7 +380,15 @@ public:
380
380
  virtual StaticString getServerName() const;
381
381
 
382
382
 
383
- /****** State inspection and configuration ******/
383
+ /****** Configuration handling ******/
384
+
385
+ bool prepareConfigChange(const Json::Value &updates,
386
+ vector<ConfigKit::Error> &errors, ControllerConfigChangeRequest &req);
387
+ void commitConfigChange(ControllerConfigChangeRequest &req)
388
+ BOOST_NOEXCEPT_OR_NOTHROW;
389
+
390
+
391
+ /****** State and configuration ******/
384
392
 
385
393
  unsigned int getThreadNumber() const; // Thread-safe
386
394
  virtual Json::Value inspectStateAsJson() const;
@@ -377,7 +377,7 @@ Controller::endRequestWithErrorResponse(Client **c, Request **r, const StaticStr
377
377
  bool
378
378
  Controller::friendlyErrorPagesEnabled(Request *req) {
379
379
  bool defaultValue;
380
- const StaticString &defaultStr = req->configCache->friendlyErrorPages;
380
+ const StaticString &defaultStr = req->config->friendlyErrorPages;
381
381
  if (defaultStr == "auto") {
382
382
  defaultValue = (req->options.environment == "development");
383
383
  } else {
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2017 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+ #include <Core/Controller.h>
27
+
28
+ namespace Passenger {
29
+ namespace Core {
30
+
31
+ using namespace std;
32
+
33
+
34
+ /****************************
35
+ *
36
+ * Private methods
37
+ *
38
+ ****************************/
39
+
40
+
41
+ bool
42
+ Controller::prepareConfigChange(const Json::Value &updates,
43
+ vector<ConfigKit::Error> &errors,
44
+ ControllerConfigChangeRequest &req)
45
+ {
46
+ if (ParentClass::prepareConfigChange(updates, errors, req.forParent)) {
47
+ req.mainConfig.reset(new ControllerMainConfig(
48
+ *req.forParent.forParent.config));
49
+ req.requestConfig.reset(new ControllerRequestConfig(
50
+ *req.forParent.forParent.config));
51
+ }
52
+ return errors.empty();
53
+ }
54
+
55
+ void
56
+ Controller::commitConfigChange(ControllerConfigChangeRequest &req)
57
+ BOOST_NOEXCEPT_OR_NOTHROW
58
+ {
59
+ ParentClass::commitConfigChange(req.forParent);
60
+ mainConfig.swap(*req.mainConfig);
61
+ requestConfig.swap(req.requestConfig);
62
+ getContext()->defaultFileBufferedChannelConfig.bufferDir =
63
+ config["data_buffer_dir"].asString();
64
+ }
65
+
66
+
67
+ } // namespace Core
68
+ } // namespace Passenger
@@ -31,6 +31,7 @@
31
31
  #include <string.h>
32
32
 
33
33
  #include <ConfigKit/ConfigKit.h>
34
+ #include <ConfigKit/ValidationUtils.h>
34
35
  #include <MemoryKit/palloc.h>
35
36
  #include <ServerKit/HttpServer.h>
36
37
  #include <Constants.h>
@@ -113,6 +114,7 @@ private:
113
114
  add("force_max_concurrent_requests_per_process", INT_TYPE, OPTIONAL, -1);
114
115
  add("abort_websockets_on_process_shutdown", BOOL_TYPE, OPTIONAL, true);
115
116
  add("load_shell_envvars", BOOL_TYPE, OPTIONAL, false);
117
+ add("max_requests", UINT_TYPE, OPTIONAL, 0);
116
118
 
117
119
  // Single app mode options
118
120
  add("app_root", STRING_TYPE, OPTIONAL);
@@ -128,6 +130,7 @@ private:
128
130
  addValidator(validate);
129
131
  addValidator(validateMultiAppMode);
130
132
  addValidator(validateSingleAppMode);
133
+ addValidator(ConfigKit::validateIntegrationMode);
131
134
  }
132
135
 
133
136
  static Json::Value inferDefaultValueForDefaultGroup(const ConfigKit::Store &config) {
@@ -177,15 +180,15 @@ private:
177
180
  }
178
181
 
179
182
  if (config["app_root"].isNull()) {
180
- errors.push_back(Error("If '{{multi_app}}' is set"
183
+ errors.push_back(Error("If '{{multi_app}}' is not set"
181
184
  " then '{{app_root}}' is required"));
182
185
  }
183
186
  if (config["app_type"].isNull()) {
184
- errors.push_back(Error("If '{{multi_app}}' is set"
187
+ errors.push_back(Error("If '{{multi_app}}' is not set"
185
188
  " then '{{app_type}}' is required"));
186
189
  }
187
190
  if (config["startup_file"].isNull()) {
188
- errors.push_back(Error("If '{{multi_app}}' is set"
191
+ errors.push_back(Error("If '{{multi_app}}' is not set"
189
192
  " then '{{startup_file}}' is required"));
190
193
  }
191
194
 
@@ -228,7 +231,17 @@ public:
228
231
  }
229
232
  };
230
233
 
231
- class ControllerMainConfigCache {
234
+ /**
235
+ * A structure that caches controller configuration which is allowed to
236
+ * change at any time, even during the middle of a request.
237
+ */
238
+ class ControllerMainConfig {
239
+ private:
240
+ StaticString createServerLogName() {
241
+ string name = "ServerThr." + toString(threadNumber);
242
+ return psg_pstrdup(pool, name);
243
+ }
244
+
232
245
  public:
233
246
  psg_pool_t *pool;
234
247
 
@@ -245,49 +258,63 @@ public:
245
258
  /*******************/
246
259
  /*******************/
247
260
 
248
- ControllerMainConfigCache(const ConfigKit::Store &initialConfig)
261
+ ControllerMainConfig(const ConfigKit::Store &config)
249
262
  : pool(psg_create_pool(1024)),
250
263
 
251
- threadNumber(0),
252
- statThrottleRate(0),
253
- responseBufferHighWatermark(0),
254
- benchmarkMode(BM_UNKNOWN),
255
- userSwitching(false),
256
- stickySessions(false),
257
- gracefulExit(0)
264
+ threadNumber(config["thread_number"].asUInt()),
265
+ statThrottleRate(config["stat_throttle_rate"].asUInt()),
266
+ responseBufferHighWatermark(config["response_buffer_high_watermark"].asUInt()),
267
+ integrationMode(psg_pstrdup(pool, config["integration_mode"].asString())),
268
+ serverLogName(createServerLogName()),
269
+ benchmarkMode(parseControllerBenchmarkMode(config["benchmark_mode"].asString())),
270
+ userSwitching(config["user_switching"].asBool()),
271
+ stickySessions(config["sticky_sessions"].asBool()),
272
+ gracefulExit(config["core_graceful_exit"].asBool())
258
273
 
259
274
  /*******************/
260
275
  {
261
- update(initialConfig);
262
-
263
- integrationMode = psg_pstrdup(pool, initialConfig["integration_mode"].asString());
264
-
265
- string name = "ServerThr." + toString(threadNumber);
266
- serverLogName = psg_pstrdup(pool, name);
267
-
268
276
  /*******************/
269
277
  }
270
278
 
271
- ~ControllerMainConfigCache() {
279
+ ~ControllerMainConfig() {
272
280
  psg_destroy_pool(pool);
273
281
  }
274
282
 
275
- void update(const ConfigKit::Store &config) {
276
- threadNumber = config["thread_number"].asUInt();
277
-
278
- userSwitching = config["user_switching"].asBool();
279
- statThrottleRate = config["stat_throttle_rate"].asUInt();
280
- responseBufferHighWatermark = config["response_buffer_high_watermark"].asUInt();
281
- stickySessions = config["sticky_sessions"].asBool();
282
- gracefulExit = config["core_graceful_exit"].asBool();
283
- benchmarkMode = parseControllerBenchmarkMode(config["benchmark_mode"].asString());
283
+ void swap(ControllerMainConfig &other) BOOST_NOEXCEPT_OR_NOTHROW {
284
+ #define SWAP_BITFIELD(Type, name) \
285
+ do { \
286
+ Type tmp = name; \
287
+ name = other.name; \
288
+ other.name = tmp; \
289
+ } while (false)
290
+
291
+ std::swap(pool, other.pool);
292
+ std::swap(threadNumber, other.threadNumber);
293
+ std::swap(statThrottleRate, other.statThrottleRate);
294
+ std::swap(responseBufferHighWatermark, other.responseBufferHighWatermark);
295
+ std::swap(integrationMode, other.integrationMode);
296
+ std::swap(serverLogName, other.serverLogName);
297
+ SWAP_BITFIELD(ControllerBenchmarkMode, benchmarkMode);
298
+ SWAP_BITFIELD(bool, userSwitching);
299
+ SWAP_BITFIELD(bool, stickySessions);
300
+ SWAP_BITFIELD(bool, gracefulExit);
284
301
 
285
302
  /*******************/
303
+
304
+ #undef SWAP_BITFIELD
286
305
  }
287
306
  };
288
307
 
289
- class ControllerRequestConfigCache:
290
- public boost::intrusive_ref_counter<ControllerRequestConfigCache,
308
+ /**
309
+ * A structure that caches controller configuration that must stay the
310
+ * same for the entire duration of a request.
311
+ *
312
+ * Note that this structure has got nothing to do with per-request config
313
+ * options: options which may be configured by the web server on a
314
+ * per-request basis. That is an orthogonal concept.
315
+ */
316
+ class ControllerRequestConfig:
317
+ public boost::intrusive_ref_counter<ControllerRequestConfig,
291
318
  boost::thread_unsafe_counter>
292
319
  {
293
320
  public:
@@ -313,6 +340,7 @@ public:
313
340
  unsigned int minInstances;
314
341
  unsigned int maxPreloaderIdleTime;
315
342
  unsigned int maxRequestQueueSize;
343
+ unsigned int maxRequests;
316
344
  int forceMaxConcurrentRequestsPerProcess;
317
345
  bool singleAppMode: 1;
318
346
  bool showVersionInHeader: 1;
@@ -323,7 +351,7 @@ public:
323
351
  /*******************/
324
352
 
325
353
 
326
- ControllerRequestConfigCache(const ConfigKit::Store &config)
354
+ ControllerRequestConfig(const ConfigKit::Store &config)
327
355
  : pool(psg_create_pool(1024 * 4)),
328
356
 
329
357
  defaultRuby(psg_pstrdup(pool, config["default_ruby"].asString())),
@@ -346,6 +374,7 @@ public:
346
374
  minInstances(config["min_instances"].asUInt()),
347
375
  maxPreloaderIdleTime(config["max_preloader_idle_time"].asUInt()),
348
376
  maxRequestQueueSize(config["max_request_queue_size"].asUInt()),
377
+ maxRequests(config["max_requests"].asUInt()),
349
378
  forceMaxConcurrentRequestsPerProcess(config["force_max_concurrent_requests_per_process"].asInt()),
350
379
  singleAppMode(!config["multi_app"].asBool()),
351
380
  showVersionInHeader(config["show_version_in_header"].asBool()),
@@ -355,12 +384,19 @@ public:
355
384
  /*******************/
356
385
  { }
357
386
 
358
- ~ControllerRequestConfigCache() {
387
+ ~ControllerRequestConfig() {
359
388
  psg_destroy_pool(pool);
360
389
  }
361
390
  };
362
391
 
363
- typedef boost::intrusive_ptr<ControllerRequestConfigCache> ControllerRequestConfigCachePtr;
392
+ typedef boost::intrusive_ptr<ControllerRequestConfig> ControllerRequestConfigPtr;
393
+
394
+
395
+ struct ControllerConfigChangeRequest {
396
+ ServerKit::HttpServerConfigChangeRequest forParent;
397
+ boost::scoped_ptr<ControllerMainConfig> mainConfig;
398
+ ControllerRequestConfigPtr requestConfig;
399
+ };
364
400
 
365
401
 
366
402
  } // namespace Core