passenger 5.0.0.rc2 → 5.0.1
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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +10 -0
- data/CONTRIBUTORS +1 -0
- data/build/agents.rb +6 -0
- data/build/cxx_tests.rb +6 -0
- data/build/misc.rb +22 -1
- data/doc/Users guide Nginx.txt +12 -0
- data/ext/common/ApplicationPool2/Options.h +2 -1
- data/ext/common/ApplicationPool2/Pool.h +15 -744
- data/ext/common/ApplicationPool2/Pool/AnalyticsCollection.h +255 -0
- data/ext/common/ApplicationPool2/Pool/Debug.h +63 -0
- data/ext/common/ApplicationPool2/Pool/GarbageCollection.h +197 -0
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +127 -0
- data/ext/common/ApplicationPool2/Pool/Inspection.h +214 -0
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +85 -0
- data/ext/common/ApplicationPool2/Process.h +5 -7
- data/ext/common/Constants.h +1 -1
- data/ext/common/Hooks.h +2 -1
- data/ext/common/Utils.cpp +1 -1
- data/ext/common/Utils/JsonUtils.h +37 -1
- data/ext/common/agents/Base.cpp +45 -40
- data/ext/common/agents/Base.h +3 -2
- data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +12 -10
- data/ext/nginx/Configuration.c +4 -1
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +7 -1
- data/lib/phusion_passenger/config/restart_app_command.rb +40 -2
- data/lib/phusion_passenger/config/utils.rb +3 -5
- data/lib/phusion_passenger/utils/ansi_colors.rb +28 -21
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +27 -10
- data/resources/templates/standalone/config.erb +4 -4
- data/test/cxx/CxxTestMain.cpp +10 -22
- metadata +10 -4
- metadata.gz.asc +7 -7
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzQxOGI3N2E5ZWJiMjU3MGY2YmI4NzAxYWQ1ZTdlYTA3Yjk5N2FiMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjYxYTNjYjU0M2IxZWVjNzFmN2VmZGM2NWRkODg2NjliMTRiODE5Nw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWNmNjM1MWEzYWU3ZjA3MjM3NmI2ODNlOWQ1MDcxYzUwMTU2NWEyZjJjZjc0
|
10
|
+
NDlhMDJjMTdlOWJlYjcxYmI5OGU0ODczOWU2Y2NjZjQzOWMwM2I3YmY0Y2Rm
|
11
|
+
NzZhNWY0MzY0M2VhMzRhMDQ0MjExNzdlYTM2OGU3YzdmNmU0NDU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTg5MGY4MTZjYTdkNmMzYjFlNDNhM2U3M2U1ODc1M2QxY2I2NDI1MTBlYzIz
|
14
|
+
NGU4MjVkN2JjZmNlMzg0MDNjNzhiOWZkNGRlMDMxMGZlYzc2NDVlMzkwN2Iy
|
15
|
+
MTBkYTA2OWFhOTM4MWU5MmUyZDRhMDE4MmJlN2U4NmNmNDc3MzM=
|
checksums.yaml.gz.asc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
|
3
3
|
Comment: GPGTools - http://gpgtools.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJU9xtNAAoJECrHRaUKISqMJQAIAJrl0J6b4TJ5HELJjdVBV3Qq
|
6
|
+
nZXFQt1JW6nf2i2/vAabc1LPG4RcMakOuzKmn3HLFuxasaZXHhrNtAMLboaIAs7n
|
7
|
+
Hk2PuOh01nvbLm/mSVajzfRL9EkUfjJpoFtLfwlRt5c7J++PmbdFdNucsAYzIYgl
|
8
|
+
12nRnu6CUc7SxVki6QC5mZwJeKcR/QvzCWG7bJ2NDvvQWoKcmkksHlBmSOhPQWC9
|
9
|
+
lExE5ZgZSjmjMeBd1peheNLPW62SVlZBKOgA32yA5wNg/KqZ88YalxQp82Pit44N
|
10
|
+
9iCA7A3PW+dUcrjbmXRYKDYSOg0SIAJvjCdRhHdcssbQPlGVbFrEZfRHrWxaRVw=
|
11
|
+
=xWOs
|
12
12
|
-----END PGP SIGNATURE-----
|
data.tar.gz.asc
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
|
3
3
|
Comment: GPGTools - http://gpgtools.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJU9xtNAAoJECrHRaUKISqMRNsIAJ3SdZ3briMF68aVBwnDb9Ht
|
6
|
+
z4uRqGROnKA/FX7EpVRtxEypVaArGgvfSI+C2jho91GIBWoEL5S5YEbRL3RwUci0
|
7
|
+
Pr4Ts+g9OYvmzYFrTmzM75W8pF2nht1hm9bxu1xxdfQMo9ts8+J9vpFjPv31+d6z
|
8
|
+
o1JnVIHZXUw9NPeAUZzBN0DMozpDqY7JH1DXYzwR7uejikz3bDbTmnPq5xIv1RAO
|
9
|
+
7aR1VfOrHm3HCs8HMPXO46vfdg4bnhrzhVQgj8xKiMXQJrd6Si/Tx6kDURDGt0zr
|
10
|
+
BBxiuYcCeVVG5LDCY6PCvaUNMal7m/98xG4AFCYpe3LirpthzAo6OZTDbaI8Dbk=
|
11
|
+
=1Ov4
|
12
12
|
-----END PGP SIGNATURE-----
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
Release 5.0.1
|
2
|
+
-------------
|
3
|
+
|
4
|
+
* The `passenger-config restart-app` command is now more user friendly. When run in a terminal, it will show an interactive menu, allowing you to select the app to restart. Closes GH-1387.
|
5
|
+
* Fixed a crash bug in the handling of sticky session cookies.
|
6
|
+
* Log failed program in error message, not its command line (contributed by: paisleyrob). Closes GH-1397.
|
7
|
+
* [Nginx] Fixes cases in which Passenger overrides the Nginx handler function even when it shouldn't, for example when Passenger is disabled. Closes GH-1393.
|
8
|
+
* [Enterprise] The `sticky_sessions` and `envvars` options in Passengerfile.json is now also supported in mass deployment mode.
|
9
|
+
|
10
|
+
|
1
11
|
Release 5.0.0 release candidate 2
|
2
12
|
---------------------------------
|
3
13
|
|
data/CONTRIBUTORS
CHANGED
data/build/agents.rb
CHANGED
@@ -63,6 +63,12 @@ AGENT_OBJECTS = {
|
|
63
63
|
'ext/common/ServerKit/AcceptLoadBalancer.h',
|
64
64
|
'ext/common/ServerKit/FileBufferedChannel.h',
|
65
65
|
'ext/common/ApplicationPool2/Pool.h',
|
66
|
+
'ext/common/ApplicationPool2/Pool/AnalyticsCollection.h',
|
67
|
+
'ext/common/ApplicationPool2/Pool/GarbageCollection.h',
|
68
|
+
'ext/common/ApplicationPool2/Pool/GeneralUtils.h',
|
69
|
+
'ext/common/ApplicationPool2/Pool/ProcessUtils.h',
|
70
|
+
'ext/common/ApplicationPool2/Pool/Inspection.h',
|
71
|
+
'ext/common/ApplicationPool2/Pool/Debug.h',
|
66
72
|
'ext/common/ApplicationPool2/Group.h',
|
67
73
|
'ext/common/ApplicationPool2/Spawner.h',
|
68
74
|
'ext/common/Constants.h',
|
data/build/cxx_tests.rb
CHANGED
@@ -77,6 +77,12 @@ TEST_CXX_OBJECTS = {
|
|
77
77
|
ext/common/ApplicationPool2/SuperGroup.h
|
78
78
|
ext/common/ApplicationPool2/Group.h
|
79
79
|
ext/common/ApplicationPool2/Pool.h
|
80
|
+
ext/common/ApplicationPool2/Pool/AnalyticsCollection.h
|
81
|
+
ext/common/ApplicationPool2/Pool/GarbageCollection.h
|
82
|
+
ext/common/ApplicationPool2/Pool/GeneralUtils.h
|
83
|
+
ext/common/ApplicationPool2/Pool/ProcessUtils.h
|
84
|
+
ext/common/ApplicationPool2/Pool/Inspection.h
|
85
|
+
ext/common/ApplicationPool2/Pool/Debug.h
|
80
86
|
ext/common/ApplicationPool2/Process.h
|
81
87
|
ext/common/ApplicationPool2/Socket.h
|
82
88
|
ext/common/ApplicationPool2/Options.h
|
data/build/misc.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2015 Phusion
|
4
4
|
#
|
5
5
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
#
|
@@ -141,12 +141,33 @@ task :contributors do
|
|
141
141
|
entries.push "Gokulnath Manakkattil"
|
142
142
|
entries.push "Sean Wilkinson"
|
143
143
|
entries.push "Yichun Zhang"
|
144
|
+
entries.delete "OnixGH"
|
144
145
|
File.open("CONTRIBUTORS", "w") do |f|
|
145
146
|
f.puts(entries.sort{ |a, b| a.downcase <=> b.downcase }.join("\n"))
|
146
147
|
end
|
147
148
|
puts "Updated CONTRIBUTORS"
|
148
149
|
end
|
149
150
|
|
151
|
+
# Compile the WebHelper binary, used by Homebrew packaging.
|
152
|
+
task :webhelper => :nginx do
|
153
|
+
require 'tmpdir'
|
154
|
+
require 'logger'
|
155
|
+
PhusionPassenger.require_passenger_lib 'utils/download'
|
156
|
+
Dir.mktmpdir do |path|
|
157
|
+
Utils::Download.download("http://nginx.org/download/nginx-#{PREFERRED_NGINX_VERSION}.tar.gz",
|
158
|
+
"#{path}/nginx.tar.gz",
|
159
|
+
:connect_timeout => 30,
|
160
|
+
:idle_timeout => 30)
|
161
|
+
sh "cd '#{path}' && tar xzf nginx.tar.gz"
|
162
|
+
sh "cd '#{path}/nginx-#{PREFERRED_NGINX_VERSION}' && " +
|
163
|
+
"./configure --prefix=/tmp " +
|
164
|
+
"#{STANDALONE_NGINX_CONFIGURE_OPTIONS} " +
|
165
|
+
"--add-module='#{Dir.pwd}/ext/nginx' && " +
|
166
|
+
"make"
|
167
|
+
sh "cp '#{path}/nginx-#{PREFERRED_NGINX_VERSION}/objs/nginx' '#{AGENT_OUTPUT_DIR}nginx-#{PREFERRED_NGINX_VERSION}'"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
150
171
|
dependencies = [
|
151
172
|
COMMON_LIBRARY.link_objects,
|
152
173
|
LIBBOOST_OXT,
|
data/doc/Users guide Nginx.txt
CHANGED
@@ -430,6 +430,18 @@ Please see <<deploying_a_rack_app,Deploying a Rack-based Ruby application>>
|
|
430
430
|
and <<deploying_a_wsgi_app,Deploying a WSGI (Python) application>>
|
431
431
|
for examples.
|
432
432
|
|
433
|
+
------------------------------
|
434
|
+
server {
|
435
|
+
listen 80;
|
436
|
+
server_name www.example.com;
|
437
|
+
root /webapps/example/public;
|
438
|
+
|
439
|
+
# You must explicitly set 'passenger_enabled on', otherwise
|
440
|
+
# Phusion Passenger won't serve this app.
|
441
|
+
passenger_enabled on;
|
442
|
+
}
|
443
|
+
------------------------------
|
444
|
+
|
433
445
|
[[PassengerBaseURI]]
|
434
446
|
==== passenger_base_uri <uri>
|
435
447
|
Used to specify that the given URI is an distinct application that should
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -33,6 +33,7 @@
|
|
33
33
|
#include <Account.h>
|
34
34
|
#include <UnionStation/Core.h>
|
35
35
|
#include <UnionStation/Transaction.h>
|
36
|
+
#include <DataStructures/HashedStaticString.h>
|
36
37
|
#include <Constants.h>
|
37
38
|
#include <ResourceLocator.h>
|
38
39
|
#include <StaticString.h>
|
@@ -76,70 +76,20 @@ class Pool: public boost::enable_shared_from_this<Pool> {
|
|
76
76
|
public:
|
77
77
|
typedef void (*AbortLongRunningConnectionsCallback)(const ProcessPtr &process);
|
78
78
|
|
79
|
-
struct InspectOptions {
|
80
|
-
bool colorize;
|
81
|
-
bool verbose;
|
82
|
-
|
83
|
-
InspectOptions()
|
84
|
-
: colorize(false),
|
85
|
-
verbose(false)
|
86
|
-
{ }
|
87
|
-
|
88
|
-
InspectOptions(const VariantMap &options)
|
89
|
-
: colorize(options.getBool("colorize", false, false)),
|
90
|
-
verbose(options.getBool("verbose", false, false))
|
91
|
-
{ }
|
92
|
-
};
|
93
|
-
|
94
79
|
// Actually private, but marked public so that unit tests can access the fields.
|
95
80
|
public:
|
96
81
|
friend class SuperGroup;
|
97
82
|
friend class Group;
|
98
|
-
|
99
|
-
struct
|
100
|
-
/** Mailbox for the unit tests to receive messages on. */
|
101
|
-
MessageBoxPtr debugger;
|
102
|
-
/** Mailbox for the ApplicationPool code to receive messages on. */
|
103
|
-
MessageBoxPtr messages;
|
104
|
-
|
105
|
-
// Choose aspects to debug.
|
106
|
-
bool restarting;
|
107
|
-
bool spawning;
|
108
|
-
bool superGroup;
|
109
|
-
bool oobw;
|
110
|
-
bool testOverflowRequestQueue;
|
111
|
-
bool detachedProcessesChecker;
|
112
|
-
|
113
|
-
// The following fields may only be accessed by Pool.
|
114
|
-
boost::mutex syncher;
|
115
|
-
unsigned int spawnLoopIteration;
|
116
|
-
|
117
|
-
DebugSupport() {
|
118
|
-
debugger = boost::make_shared<MessageBox>();
|
119
|
-
messages = boost::make_shared<MessageBox>();
|
120
|
-
restarting = true;
|
121
|
-
spawning = true;
|
122
|
-
superGroup = false;
|
123
|
-
oobw = false;
|
124
|
-
detachedProcessesChecker = false;
|
125
|
-
testOverflowRequestQueue = false;
|
126
|
-
spawnLoopIteration = 0;
|
127
|
-
}
|
128
|
-
};
|
129
|
-
|
130
|
-
typedef boost::shared_ptr<DebugSupport> DebugSupportPtr;
|
83
|
+
friend class Process;
|
84
|
+
friend struct tut::ApplicationPool2_PoolTest;
|
131
85
|
|
132
86
|
SpawnerFactoryPtr spawnerFactory;
|
133
|
-
SystemMetricsCollector systemMetricsCollector;
|
134
|
-
SystemMetrics systemMetrics;
|
135
87
|
|
136
88
|
mutable boost::mutex syncher;
|
137
89
|
unsigned int max;
|
138
90
|
unsigned long long maxIdleTime;
|
139
91
|
bool selfchecking;
|
140
92
|
|
141
|
-
boost::condition_variable garbageCollectionCond;
|
142
|
-
|
143
93
|
/**
|
144
94
|
* Code can register background threads in one of these dynamic thread groups
|
145
95
|
* to ensure that threads are interrupted and/or joined properly upon Pool
|
@@ -203,168 +153,16 @@ public:
|
|
203
153
|
vector<GetWaiter> getWaitlist;
|
204
154
|
|
205
155
|
const VariantMap *agentsOptions;
|
206
|
-
DebugSupportPtr debugSupport;
|
207
|
-
|
208
|
-
static void runAllActions(const boost::container::vector<Callback> &actions) {
|
209
|
-
boost::container::vector<Callback>::const_iterator it, end = actions.end();
|
210
|
-
for (it = actions.begin(); it != end; it++) {
|
211
|
-
(*it)();
|
212
|
-
}
|
213
|
-
}
|
214
|
-
|
215
|
-
static void runAllActionsWithCopy(boost::container::vector<Callback> actions) {
|
216
|
-
runAllActions(actions);
|
217
|
-
}
|
218
|
-
|
219
|
-
static const char *maybeColorize(const InspectOptions &options, const char *color) {
|
220
|
-
if (options.colorize) {
|
221
|
-
return color;
|
222
|
-
} else {
|
223
|
-
return "";
|
224
|
-
}
|
225
|
-
}
|
226
|
-
|
227
|
-
void verifyInvariants() const {
|
228
|
-
// !a || b: logical equivalent of a IMPLIES b.
|
229
|
-
#ifndef NDEBUG
|
230
|
-
if (!selfchecking) {
|
231
|
-
return;
|
232
|
-
}
|
233
|
-
assert(!( !getWaitlist.empty() ) || ( atFullCapacityUnlocked() ));
|
234
|
-
assert(!( !atFullCapacityUnlocked() ) || ( getWaitlist.empty() ));
|
235
|
-
#endif
|
236
|
-
}
|
237
|
-
|
238
|
-
void verifyExpensiveInvariants() const {
|
239
|
-
#ifndef NDEBUG
|
240
|
-
if (!selfchecking) {
|
241
|
-
return;
|
242
|
-
}
|
243
|
-
vector<GetWaiter>::const_iterator it, end = getWaitlist.end();
|
244
|
-
for (it = getWaitlist.begin(); it != end; it++) {
|
245
|
-
const GetWaiter &waiter = *it;
|
246
|
-
const SuperGroupPtr *superGroup;
|
247
|
-
assert(!superGroups.lookup(waiter.options.getAppGroupName(), &superGroup));
|
248
|
-
}
|
249
|
-
#endif
|
250
|
-
}
|
251
|
-
|
252
|
-
void fullVerifyInvariants() const {
|
253
|
-
TRACE_POINT();
|
254
|
-
verifyInvariants();
|
255
|
-
UPDATE_TRACE_POINT();
|
256
|
-
verifyExpensiveInvariants();
|
257
|
-
UPDATE_TRACE_POINT();
|
258
|
-
|
259
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
260
|
-
while (*sg_it != NULL) {
|
261
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
262
|
-
superGroup->verifyInvariants();
|
263
|
-
foreach (GroupPtr group, superGroup->groups) {
|
264
|
-
group->verifyInvariants();
|
265
|
-
group->verifyExpensiveInvariants();
|
266
|
-
}
|
267
|
-
sg_it.next();
|
268
|
-
}
|
269
|
-
}
|
270
|
-
|
271
|
-
bool runHookScripts(const char *name,
|
272
|
-
const boost::function<void (HookScriptOptions &)> &setup) const
|
273
|
-
{
|
274
|
-
if (agentsOptions != NULL) {
|
275
|
-
string hookName = string("hook_") + name;
|
276
|
-
string spec = agentsOptions->get(hookName, false);
|
277
|
-
if (!spec.empty()) {
|
278
|
-
HookScriptOptions options;
|
279
|
-
options.agentsOptions = agentsOptions;
|
280
|
-
options.name = name;
|
281
|
-
options.spec = spec;
|
282
|
-
setup(options);
|
283
|
-
return Passenger::runHookScripts(options);
|
284
|
-
} else {
|
285
|
-
return true;
|
286
|
-
}
|
287
|
-
} else {
|
288
|
-
return true;
|
289
|
-
}
|
290
|
-
}
|
291
|
-
|
292
|
-
static const char *maybePluralize(unsigned int count, const char *singular, const char *plural) {
|
293
|
-
if (count == 1) {
|
294
|
-
return singular;
|
295
|
-
} else {
|
296
|
-
return plural;
|
297
|
-
}
|
298
|
-
}
|
299
|
-
|
300
|
-
const SpawnerConfigPtr &getSpawnerConfig() const {
|
301
|
-
return spawnerFactory->getConfig();
|
302
|
-
}
|
303
|
-
|
304
|
-
const UnionStation::CorePtr &getUnionStationCore() const {
|
305
|
-
return getSpawnerConfig()->unionStationCore;
|
306
|
-
}
|
307
|
-
|
308
|
-
const RandomGeneratorPtr &getRandomGenerator() const {
|
309
|
-
return getSpawnerConfig()->randomGenerator;
|
310
|
-
}
|
311
|
-
|
312
|
-
ProcessPtr findOldestIdleProcess(const Group *exclude = NULL) const {
|
313
|
-
ProcessPtr oldestIdleProcess;
|
314
|
-
|
315
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
316
|
-
while (*sg_it != NULL) {
|
317
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
318
|
-
const SuperGroup::GroupList &groups = superGroup->groups;
|
319
|
-
SuperGroup::GroupList::const_iterator g_it, g_end = groups.end();
|
320
|
-
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
321
|
-
const GroupPtr &group = *g_it;
|
322
|
-
if (group.get() == exclude) {
|
323
|
-
continue;
|
324
|
-
}
|
325
|
-
const ProcessList &processes = group->enabledProcesses;
|
326
|
-
ProcessList::const_iterator p_it, p_end = processes.end();
|
327
|
-
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
328
|
-
const ProcessPtr process = *p_it;
|
329
|
-
if (process->busyness() == 0
|
330
|
-
&& (oldestIdleProcess == NULL
|
331
|
-
|| process->lastUsed < oldestIdleProcess->lastUsed)
|
332
|
-
) {
|
333
|
-
oldestIdleProcess = process;
|
334
|
-
}
|
335
|
-
}
|
336
|
-
}
|
337
|
-
sg_it.next();
|
338
|
-
}
|
339
|
-
|
340
|
-
return oldestIdleProcess;
|
341
|
-
}
|
342
|
-
|
343
|
-
ProcessPtr findBestProcessToTrash() const {
|
344
|
-
ProcessPtr oldestProcess;
|
345
156
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
const GroupPtr &group = *g_it;
|
353
|
-
const ProcessList &processes = group->enabledProcesses;
|
354
|
-
ProcessList::const_iterator p_it, p_end = processes.end();
|
355
|
-
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
356
|
-
const ProcessPtr process = *p_it;
|
357
|
-
if (oldestProcess == NULL
|
358
|
-
|| process->lastUsed < oldestProcess->lastUsed) {
|
359
|
-
oldestProcess = process;
|
360
|
-
}
|
361
|
-
}
|
362
|
-
}
|
363
|
-
sg_it.next();
|
364
|
-
}
|
157
|
+
#include <ApplicationPool2/Pool/AnalyticsCollection.h>
|
158
|
+
#include <ApplicationPool2/Pool/GarbageCollection.h>
|
159
|
+
#include <ApplicationPool2/Pool/GeneralUtils.h>
|
160
|
+
#include <ApplicationPool2/Pool/ProcessUtils.h>
|
161
|
+
#include <ApplicationPool2/Pool/Inspection.h>
|
162
|
+
#include <ApplicationPool2/Pool/Debug.h>
|
365
163
|
|
366
|
-
|
367
|
-
|
164
|
+
// Actually private, but marked public so that unit tests can access the fields.
|
165
|
+
public:
|
368
166
|
|
369
167
|
/** Process all waiters on the getWaitlist. Call when capacity has become free.
|
370
168
|
* This function assigns sessions to them by calling get() on the corresponding
|
@@ -554,47 +352,6 @@ public:
|
|
554
352
|
}
|
555
353
|
}
|
556
354
|
|
557
|
-
void inspectProcessList(const InspectOptions &options, stringstream &result,
|
558
|
-
const Group *group, const ProcessList &processes) const
|
559
|
-
{
|
560
|
-
ProcessList::const_iterator p_it;
|
561
|
-
for (p_it = processes.begin(); p_it != processes.end(); p_it++) {
|
562
|
-
const ProcessPtr &process = *p_it;
|
563
|
-
char buf[128];
|
564
|
-
char cpubuf[10];
|
565
|
-
char membuf[10];
|
566
|
-
|
567
|
-
snprintf(cpubuf, sizeof(cpubuf), "%d%%", (int) process->metrics.cpu);
|
568
|
-
snprintf(membuf, sizeof(membuf), "%ldM",
|
569
|
-
(unsigned long) (process->metrics.realMemory() / 1024));
|
570
|
-
snprintf(buf, sizeof(buf),
|
571
|
-
" * PID: %-5lu Sessions: %-2u Processed: %-5u Uptime: %s\n"
|
572
|
-
" CPU: %-5s Memory : %-5s Last used: %s ago",
|
573
|
-
(unsigned long) process->pid,
|
574
|
-
process->sessions,
|
575
|
-
process->processed,
|
576
|
-
process->uptime().c_str(),
|
577
|
-
cpubuf,
|
578
|
-
membuf,
|
579
|
-
distanceOfTimeInWords(process->lastUsed / 1000000).c_str());
|
580
|
-
result << buf << endl;
|
581
|
-
|
582
|
-
if (process->enabled == Process::DISABLING) {
|
583
|
-
result << " Disabling..." << endl;
|
584
|
-
} else if (process->enabled == Process::DISABLED) {
|
585
|
-
result << " DISABLED" << endl;
|
586
|
-
} else if (process->enabled == Process::DETACHED) {
|
587
|
-
result << " Shutting down..." << endl;
|
588
|
-
}
|
589
|
-
|
590
|
-
const Socket *socket;
|
591
|
-
if (options.verbose && (socket = process->sockets.findSocketWithName("http")) != NULL) {
|
592
|
-
result << " URL : http://" << replaceString(socket->address, "tcp://", "") << endl;
|
593
|
-
result << " Password: " << StaticString(group->secret, Group::SECRET_SIZE) << endl;
|
594
|
-
}
|
595
|
-
}
|
596
|
-
}
|
597
|
-
|
598
355
|
struct DetachSuperGroupWaitTicket {
|
599
356
|
boost::mutex syncher;
|
600
357
|
boost::condition_variable cond;
|
@@ -664,374 +421,12 @@ public:
|
|
664
421
|
}
|
665
422
|
}
|
666
423
|
|
667
|
-
struct GarbageCollectorState {
|
668
|
-
unsigned long long now;
|
669
|
-
unsigned long long nextGcRunTime;
|
670
|
-
boost::container::vector<Callback> actions;
|
671
|
-
};
|
672
|
-
|
673
|
-
static void garbageCollect(PoolPtr self) {
|
674
|
-
TRACE_POINT();
|
675
|
-
{
|
676
|
-
ScopedLock lock(self->syncher);
|
677
|
-
self->garbageCollectionCond.timed_wait(lock,
|
678
|
-
posix_time::seconds(5));
|
679
|
-
}
|
680
|
-
while (!this_thread::interruption_requested()) {
|
681
|
-
try {
|
682
|
-
UPDATE_TRACE_POINT();
|
683
|
-
unsigned long long sleepTime = self->realGarbageCollect();
|
684
|
-
UPDATE_TRACE_POINT();
|
685
|
-
ScopedLock lock(self->syncher);
|
686
|
-
self->garbageCollectionCond.timed_wait(lock,
|
687
|
-
posix_time::microseconds(sleepTime));
|
688
|
-
} catch (const thread_interrupted &) {
|
689
|
-
break;
|
690
|
-
} catch (const tracable_exception &e) {
|
691
|
-
P_WARN("ERROR: " << e.what() << "\n Backtrace:\n" << e.backtrace());
|
692
|
-
}
|
693
|
-
}
|
694
|
-
}
|
695
|
-
|
696
|
-
void maybeUpdateNextGcRuntime(GarbageCollectorState &state, unsigned long candidate) {
|
697
|
-
if (state.nextGcRunTime == 0 || candidate < state.nextGcRunTime) {
|
698
|
-
state.nextGcRunTime = candidate;
|
699
|
-
}
|
700
|
-
}
|
701
|
-
|
702
|
-
void checkWhetherProcessCanBeGarbageCollected(GarbageCollectorState &state,
|
703
|
-
const GroupPtr &group, const ProcessPtr &process, ProcessList &output)
|
704
|
-
{
|
705
|
-
assert(maxIdleTime > 0);
|
706
|
-
unsigned long long processGcTime = process->lastUsed + maxIdleTime;
|
707
|
-
if (process->sessions == 0
|
708
|
-
&& state.now >= processGcTime
|
709
|
-
&& (unsigned long) group->getProcessCount() > group->options.minProcesses)
|
710
|
-
{
|
711
|
-
if (output.capacity() == 0) {
|
712
|
-
output.reserve(group->enabledCount);
|
713
|
-
}
|
714
|
-
output.push_back(process);
|
715
|
-
} else {
|
716
|
-
maybeUpdateNextGcRuntime(state, processGcTime);
|
717
|
-
}
|
718
|
-
}
|
719
|
-
|
720
|
-
void garbageCollectProcessesInGroup(GarbageCollectorState &state,
|
721
|
-
const GroupPtr &group)
|
722
|
-
{
|
723
|
-
ProcessList &processes = group->enabledProcesses;
|
724
|
-
ProcessList processesToGc;
|
725
|
-
ProcessList::iterator p_it, p_end = processes.end();
|
726
|
-
|
727
|
-
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
728
|
-
const ProcessPtr &process = *p_it;
|
729
|
-
checkWhetherProcessCanBeGarbageCollected(state, group, process,
|
730
|
-
processesToGc);
|
731
|
-
}
|
732
|
-
|
733
|
-
p_end = processesToGc.end();
|
734
|
-
for (p_it = processesToGc.begin(); p_it != p_end; p_it++) {
|
735
|
-
ProcessPtr process = *p_it;
|
736
|
-
P_DEBUG("Garbage collect idle process: " << process->inspect() <<
|
737
|
-
", group=" << group->name);
|
738
|
-
group->detach(process, state.actions);
|
739
|
-
}
|
740
|
-
}
|
741
|
-
|
742
|
-
void maybeCleanPreloader(GarbageCollectorState &state, const GroupPtr &group) {
|
743
|
-
if (group->spawner->cleanable() && group->options.getMaxPreloaderIdleTime() != 0) {
|
744
|
-
unsigned long long spawnerGcTime =
|
745
|
-
group->spawner->lastUsed() +
|
746
|
-
group->options.getMaxPreloaderIdleTime() * 1000000;
|
747
|
-
if (state.now >= spawnerGcTime) {
|
748
|
-
P_DEBUG("Garbage collect idle spawner: group=" << group->name);
|
749
|
-
group->cleanupSpawner(state.actions);
|
750
|
-
} else {
|
751
|
-
maybeUpdateNextGcRuntime(state, spawnerGcTime);
|
752
|
-
}
|
753
|
-
}
|
754
|
-
}
|
755
|
-
|
756
|
-
unsigned long long realGarbageCollect() {
|
757
|
-
TRACE_POINT();
|
758
|
-
ScopedLock lock(syncher);
|
759
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
760
|
-
GarbageCollectorState state;
|
761
|
-
state.now = SystemTime::getUsec();
|
762
|
-
state.nextGcRunTime = 0;
|
763
|
-
|
764
|
-
P_DEBUG("Garbage collection time...");
|
765
|
-
verifyInvariants();
|
766
|
-
|
767
|
-
// For all supergroups and groups...
|
768
|
-
while (*sg_it != NULL) {
|
769
|
-
const SuperGroupPtr superGroup = sg_it.getValue();
|
770
|
-
SuperGroup::GroupList &groups = superGroup->groups;
|
771
|
-
SuperGroup::GroupList::iterator g_it, g_end = groups.end();
|
772
|
-
|
773
|
-
superGroup->verifyInvariants();
|
774
|
-
|
775
|
-
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
776
|
-
GroupPtr group = *g_it;
|
777
|
-
|
778
|
-
if (maxIdleTime > 0) {
|
779
|
-
// ...detach processes that have been idle for more than maxIdleTime.
|
780
|
-
garbageCollectProcessesInGroup(state, group);
|
781
|
-
}
|
782
|
-
|
783
|
-
group->verifyInvariants();
|
784
|
-
|
785
|
-
// ...cleanup the spawner if it's been idle for more than preloaderIdleTime.
|
786
|
-
maybeCleanPreloader(state, group);
|
787
|
-
}
|
788
|
-
|
789
|
-
superGroup->verifyInvariants();
|
790
|
-
sg_it.next();
|
791
|
-
}
|
792
|
-
|
793
|
-
verifyInvariants();
|
794
|
-
lock.unlock();
|
795
|
-
|
796
|
-
// Schedule next garbage collection run.
|
797
|
-
unsigned long long sleepTime;
|
798
|
-
if (state.nextGcRunTime == 0 || state.nextGcRunTime <= state.now) {
|
799
|
-
if (maxIdleTime == 0) {
|
800
|
-
sleepTime = 10 * 60 * 1000000;
|
801
|
-
} else {
|
802
|
-
sleepTime = maxIdleTime;
|
803
|
-
}
|
804
|
-
} else {
|
805
|
-
sleepTime = state.nextGcRunTime - state.now;
|
806
|
-
}
|
807
|
-
P_DEBUG("Garbage collection done; next garbage collect in " <<
|
808
|
-
std::fixed << std::setprecision(3) << (sleepTime / 1000000.0) << " sec");
|
809
|
-
|
810
|
-
UPDATE_TRACE_POINT();
|
811
|
-
runAllActions(state.actions);
|
812
|
-
UPDATE_TRACE_POINT();
|
813
|
-
state.actions.clear();
|
814
|
-
return sleepTime;
|
815
|
-
}
|
816
|
-
|
817
|
-
struct UnionStationLogEntry {
|
818
|
-
string groupName;
|
819
|
-
const char *category;
|
820
|
-
string key;
|
821
|
-
string data;
|
822
|
-
};
|
823
|
-
|
824
|
-
static void collectAnalytics(PoolPtr self) {
|
825
|
-
TRACE_POINT();
|
826
|
-
syscalls::usleep(3000000);
|
827
|
-
while (!this_thread::interruption_requested()) {
|
828
|
-
try {
|
829
|
-
UPDATE_TRACE_POINT();
|
830
|
-
self->realCollectAnalytics();
|
831
|
-
} catch (const thread_interrupted &) {
|
832
|
-
break;
|
833
|
-
} catch (const tracable_exception &e) {
|
834
|
-
P_WARN("ERROR: " << e.what() << "\n Backtrace:\n" << e.backtrace());
|
835
|
-
}
|
836
|
-
|
837
|
-
// Sleep for about 4 seconds, aligned to seconds boundary
|
838
|
-
// for saving power on laptops.
|
839
|
-
UPDATE_TRACE_POINT();
|
840
|
-
unsigned long long currentTime = SystemTime::getUsec();
|
841
|
-
unsigned long long deadline =
|
842
|
-
roundUp<unsigned long long>(currentTime, 1000000) + 4000000;
|
843
|
-
P_DEBUG("Analytics collection done; next analytics collection in " <<
|
844
|
-
std::fixed << std::setprecision(3) << ((deadline - currentTime) / 1000000.0) <<
|
845
|
-
" sec");
|
846
|
-
try {
|
847
|
-
syscalls::usleep(deadline - currentTime);
|
848
|
-
} catch (const thread_interrupted &) {
|
849
|
-
break;
|
850
|
-
} catch (const tracable_exception &e) {
|
851
|
-
P_WARN("ERROR: " << e.what() << "\n Backtrace:\n" << e.backtrace());
|
852
|
-
}
|
853
|
-
}
|
854
|
-
}
|
855
|
-
|
856
|
-
static void collectPids(const ProcessList &processes, vector<pid_t> &pids) {
|
857
|
-
foreach (const ProcessPtr &process, processes) {
|
858
|
-
pids.push_back(process->pid);
|
859
|
-
}
|
860
|
-
}
|
861
|
-
|
862
|
-
static void updateProcessMetrics(const ProcessList &processes,
|
863
|
-
const ProcessMetricMap &allMetrics,
|
864
|
-
vector<ProcessPtr> &processesToDetach)
|
865
|
-
{
|
866
|
-
foreach (const ProcessPtr &process, processes) {
|
867
|
-
ProcessMetricMap::const_iterator metrics_it =
|
868
|
-
allMetrics.find(process->pid);
|
869
|
-
if (metrics_it != allMetrics.end()) {
|
870
|
-
process->metrics = metrics_it->second;
|
871
|
-
// If the process is missing from 'allMetrics' then either 'ps'
|
872
|
-
// failed or the process really is gone. We double check by sending
|
873
|
-
// it a signal.
|
874
|
-
} else if (!process->dummy && !process->osProcessExists()) {
|
875
|
-
P_WARN("Process " << process->inspect() << " no longer exists! "
|
876
|
-
"Detaching it from the pool.");
|
877
|
-
processesToDetach.push_back(process);
|
878
|
-
}
|
879
|
-
}
|
880
|
-
}
|
881
|
-
|
882
|
-
void prepareUnionStationProcessStateLogs(vector<UnionStationLogEntry> &logEntries,
|
883
|
-
const GroupPtr &group) const
|
884
|
-
{
|
885
|
-
const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
|
886
|
-
if (group->options.analytics && unionStationCore != NULL) {
|
887
|
-
logEntries.push_back(UnionStationLogEntry());
|
888
|
-
UnionStationLogEntry &entry = logEntries.back();
|
889
|
-
stringstream stream;
|
890
|
-
|
891
|
-
stream << "Group: <group>";
|
892
|
-
group->inspectXml(stream, false);
|
893
|
-
stream << "</group>";
|
894
|
-
|
895
|
-
entry.groupName = group->options.getAppGroupName();
|
896
|
-
entry.category = "processes";
|
897
|
-
entry.key = group->options.unionStationKey;
|
898
|
-
entry.data = stream.str();
|
899
|
-
}
|
900
|
-
}
|
901
|
-
|
902
|
-
void prepareUnionStationSystemMetricsLogs(vector<UnionStationLogEntry> &logEntries,
|
903
|
-
const GroupPtr &group) const
|
904
|
-
{
|
905
|
-
const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
|
906
|
-
if (group->options.analytics && unionStationCore != NULL) {
|
907
|
-
logEntries.push_back(UnionStationLogEntry());
|
908
|
-
UnionStationLogEntry &entry = logEntries.back();
|
909
|
-
stringstream stream;
|
910
|
-
|
911
|
-
stream << "System metrics: ";
|
912
|
-
systemMetrics.toXml(stream);
|
913
|
-
|
914
|
-
entry.groupName = group->options.getAppGroupName();
|
915
|
-
entry.category = "system_metrics";
|
916
|
-
entry.key = group->options.unionStationKey;
|
917
|
-
entry.data = stream.str();
|
918
|
-
}
|
919
|
-
}
|
920
|
-
|
921
|
-
void realCollectAnalytics() {
|
922
|
-
TRACE_POINT();
|
923
|
-
this_thread::disable_interruption di;
|
924
|
-
this_thread::disable_syscall_interruption dsi;
|
925
|
-
vector<pid_t> pids;
|
926
|
-
unsigned int max;
|
927
|
-
|
928
|
-
P_DEBUG("Analytics collection time...");
|
929
|
-
// Collect all the PIDs.
|
930
|
-
{
|
931
|
-
UPDATE_TRACE_POINT();
|
932
|
-
LockGuard l(syncher);
|
933
|
-
max = this->max;
|
934
|
-
}
|
935
|
-
pids.reserve(max);
|
936
|
-
{
|
937
|
-
UPDATE_TRACE_POINT();
|
938
|
-
LockGuard l(syncher);
|
939
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
940
|
-
|
941
|
-
while (*sg_it != NULL) {
|
942
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
943
|
-
SuperGroup::GroupList::const_iterator g_it, g_end = superGroup->groups.end();
|
944
|
-
|
945
|
-
for (g_it = superGroup->groups.begin(); g_it != g_end; g_it++) {
|
946
|
-
const GroupPtr &group = *g_it;
|
947
|
-
collectPids(group->enabledProcesses, pids);
|
948
|
-
collectPids(group->disablingProcesses, pids);
|
949
|
-
collectPids(group->disabledProcesses, pids);
|
950
|
-
}
|
951
|
-
sg_it.next();
|
952
|
-
}
|
953
|
-
}
|
954
|
-
|
955
|
-
// Collect process metrics and system and store them in the
|
956
|
-
// data structures. Later, we log them to Union Station.
|
957
|
-
ProcessMetricMap processMetrics;
|
958
|
-
try {
|
959
|
-
UPDATE_TRACE_POINT();
|
960
|
-
processMetrics = ProcessMetricsCollector().collect(pids);
|
961
|
-
} catch (const ParseException &) {
|
962
|
-
P_WARN("Unable to collect process metrics: cannot parse 'ps' output.");
|
963
|
-
return;
|
964
|
-
}
|
965
|
-
try {
|
966
|
-
UPDATE_TRACE_POINT();
|
967
|
-
systemMetricsCollector.collect(systemMetrics);
|
968
|
-
} catch (const RuntimeException &e) {
|
969
|
-
P_WARN("Unable to collect system metrics: " << e.what());
|
970
|
-
return;
|
971
|
-
}
|
972
|
-
|
973
|
-
{
|
974
|
-
UPDATE_TRACE_POINT();
|
975
|
-
vector<UnionStationLogEntry> logEntries;
|
976
|
-
vector<ProcessPtr> processesToDetach;
|
977
|
-
boost::container::vector<Callback> actions;
|
978
|
-
ScopedLock l(syncher);
|
979
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
980
|
-
|
981
|
-
UPDATE_TRACE_POINT();
|
982
|
-
while (*sg_it != NULL) {
|
983
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
984
|
-
SuperGroup::GroupList::iterator g_it, g_end = superGroup->groups.end();
|
985
|
-
|
986
|
-
for (g_it = superGroup->groups.begin(); g_it != g_end; g_it++) {
|
987
|
-
const GroupPtr &group = *g_it;
|
988
|
-
|
989
|
-
updateProcessMetrics(group->enabledProcesses, processMetrics, processesToDetach);
|
990
|
-
updateProcessMetrics(group->disablingProcesses, processMetrics, processesToDetach);
|
991
|
-
updateProcessMetrics(group->disabledProcesses, processMetrics, processesToDetach);
|
992
|
-
prepareUnionStationProcessStateLogs(logEntries, group);
|
993
|
-
prepareUnionStationSystemMetricsLogs(logEntries, group);
|
994
|
-
}
|
995
|
-
sg_it.next();
|
996
|
-
}
|
997
|
-
|
998
|
-
UPDATE_TRACE_POINT();
|
999
|
-
foreach (const ProcessPtr process, processesToDetach) {
|
1000
|
-
detachProcessUnlocked(process, actions);
|
1001
|
-
}
|
1002
|
-
UPDATE_TRACE_POINT();
|
1003
|
-
processesToDetach.clear();
|
1004
|
-
|
1005
|
-
l.unlock();
|
1006
|
-
UPDATE_TRACE_POINT();
|
1007
|
-
if (!logEntries.empty()) {
|
1008
|
-
const UnionStation::CorePtr &unionStationCore = getUnionStationCore();
|
1009
|
-
while (!logEntries.empty()) {
|
1010
|
-
UnionStationLogEntry &entry = logEntries.back();
|
1011
|
-
UnionStation::TransactionPtr transaction =
|
1012
|
-
unionStationCore->newTransaction(
|
1013
|
-
entry.groupName,
|
1014
|
-
entry.category,
|
1015
|
-
entry.key);
|
1016
|
-
transaction->message(entry.data);
|
1017
|
-
logEntries.pop_back();
|
1018
|
-
}
|
1019
|
-
}
|
1020
|
-
|
1021
|
-
UPDATE_TRACE_POINT();
|
1022
|
-
runAllActions(actions);
|
1023
|
-
UPDATE_TRACE_POINT();
|
1024
|
-
// Run destructors with updated trace point.
|
1025
|
-
actions.clear();
|
1026
|
-
}
|
1027
|
-
}
|
1028
|
-
|
1029
424
|
SuperGroupPtr createSuperGroup(const Options &options) {
|
1030
425
|
SuperGroupPtr superGroup = boost::make_shared<SuperGroup>(this,
|
1031
426
|
options);
|
1032
427
|
superGroup->initialize();
|
1033
428
|
superGroups.insert(options.getAppGroupName(), superGroup);
|
1034
|
-
|
429
|
+
wakeupGarbageCollector();
|
1035
430
|
return superGroup;
|
1036
431
|
}
|
1037
432
|
|
@@ -1093,16 +488,8 @@ public:
|
|
1093
488
|
/** Must be called right after construction. */
|
1094
489
|
void initialize() {
|
1095
490
|
LockGuard l(syncher);
|
1096
|
-
|
1097
|
-
|
1098
|
-
"Pool analytics collector",
|
1099
|
-
POOL_HELPER_THREAD_STACK_SIZE
|
1100
|
-
);
|
1101
|
-
interruptableThreads.create_thread(
|
1102
|
-
boost::bind(garbageCollect, shared_from_this()),
|
1103
|
-
"Pool garbage collector",
|
1104
|
-
POOL_HELPER_THREAD_STACK_SIZE
|
1105
|
-
);
|
491
|
+
initializeAnalyticsCollection();
|
492
|
+
initializeGarbageCollection();
|
1106
493
|
}
|
1107
494
|
|
1108
495
|
void initDebugging() {
|
@@ -1225,7 +612,7 @@ public:
|
|
1225
612
|
superGroup = boost::make_shared<SuperGroup>(this, options);
|
1226
613
|
superGroup->initialize();
|
1227
614
|
superGroups.insert(options.getAppGroupName(), superGroup);
|
1228
|
-
|
615
|
+
wakeupGarbageCollector();
|
1229
616
|
SessionPtr session = superGroup->get(options, callback,
|
1230
617
|
actions);
|
1231
618
|
/* The SuperGroup is still initializing so the callback
|
@@ -1333,7 +720,7 @@ public:
|
|
1333
720
|
void setMaxIdleTime(unsigned long long value) {
|
1334
721
|
LockGuard l(syncher);
|
1335
722
|
maxIdleTime = value;
|
1336
|
-
|
723
|
+
wakeupGarbageCollector();
|
1337
724
|
}
|
1338
725
|
|
1339
726
|
void enableSelfChecking(bool enabled) {
|
@@ -1622,122 +1009,6 @@ public:
|
|
1622
1009
|
}
|
1623
1010
|
return false;
|
1624
1011
|
}
|
1625
|
-
|
1626
|
-
string inspect(const InspectOptions &options = InspectOptions(), bool lock = true) const {
|
1627
|
-
DynamicScopedLock l(syncher, lock);
|
1628
|
-
stringstream result;
|
1629
|
-
const char *headerColor = maybeColorize(options, ANSI_COLOR_YELLOW ANSI_COLOR_BLUE_BG ANSI_COLOR_BOLD);
|
1630
|
-
const char *resetColor = maybeColorize(options, ANSI_COLOR_RESET);
|
1631
|
-
|
1632
|
-
result << headerColor << "----------- General information -----------" << resetColor << endl;
|
1633
|
-
result << "Max pool size : " << max << endl;
|
1634
|
-
result << "Processes : " << getProcessCount(false) << endl;
|
1635
|
-
result << "Requests in top-level queue : " << getWaitlist.size() << endl;
|
1636
|
-
if (options.verbose) {
|
1637
|
-
unsigned int i = 0;
|
1638
|
-
foreach (const GetWaiter &waiter, getWaitlist) {
|
1639
|
-
result << " " << i << ": " << waiter.options.getAppGroupName() << endl;
|
1640
|
-
i++;
|
1641
|
-
}
|
1642
|
-
}
|
1643
|
-
result << endl;
|
1644
|
-
|
1645
|
-
result << headerColor << "----------- Application groups -----------" << resetColor << endl;
|
1646
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
1647
|
-
while (*sg_it != NULL) {
|
1648
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
1649
|
-
const Group *group = superGroup->defaultGroup;
|
1650
|
-
ProcessList::const_iterator p_it;
|
1651
|
-
|
1652
|
-
if (group != NULL) {
|
1653
|
-
result << group->name << ":" << endl;
|
1654
|
-
result << " App root: " << group->options.appRoot << endl;
|
1655
|
-
if (group->restarting()) {
|
1656
|
-
result << " (restarting...)" << endl;
|
1657
|
-
}
|
1658
|
-
if (group->spawning()) {
|
1659
|
-
if (group->processesBeingSpawned == 0) {
|
1660
|
-
result << " (spawning...)" << endl;
|
1661
|
-
} else {
|
1662
|
-
result << " (spawning " << group->processesBeingSpawned << " new " <<
|
1663
|
-
maybePluralize(group->processesBeingSpawned, "process", "processes") <<
|
1664
|
-
"...)" << endl;
|
1665
|
-
}
|
1666
|
-
}
|
1667
|
-
result << " Requests in queue: " << group->getWaitlist.size() << endl;
|
1668
|
-
inspectProcessList(options, result, group, group->enabledProcesses);
|
1669
|
-
inspectProcessList(options, result, group, group->disablingProcesses);
|
1670
|
-
inspectProcessList(options, result, group, group->disabledProcesses);
|
1671
|
-
inspectProcessList(options, result, group, group->detachedProcesses);
|
1672
|
-
result << endl;
|
1673
|
-
}
|
1674
|
-
sg_it.next();
|
1675
|
-
}
|
1676
|
-
return result.str();
|
1677
|
-
}
|
1678
|
-
|
1679
|
-
string toXml(bool includeSecrets = true, bool lock = true) const {
|
1680
|
-
DynamicScopedLock l(syncher, lock);
|
1681
|
-
stringstream result;
|
1682
|
-
SuperGroupMap::ConstIterator sg_it(superGroups);
|
1683
|
-
SuperGroup::GroupList::const_iterator g_it;
|
1684
|
-
ProcessList::const_iterator p_it;
|
1685
|
-
|
1686
|
-
result << "<?xml version=\"1.0\" encoding=\"iso8859-1\" ?>\n";
|
1687
|
-
result << "<info version=\"3\">";
|
1688
|
-
|
1689
|
-
result << "<passenger_version>" << PASSENGER_VERSION << "</passenger_version>";
|
1690
|
-
result << "<process_count>" << getProcessCount(false) << "</process_count>";
|
1691
|
-
result << "<max>" << max << "</max>";
|
1692
|
-
result << "<capacity_used>" << capacityUsedUnlocked() << "</capacity_used>";
|
1693
|
-
result << "<get_wait_list_size>" << getWaitlist.size() << "</get_wait_list_size>";
|
1694
|
-
|
1695
|
-
if (includeSecrets) {
|
1696
|
-
vector<GetWaiter>::const_iterator w_it, w_end = getWaitlist.end();
|
1697
|
-
|
1698
|
-
result << "<get_wait_list>";
|
1699
|
-
for (w_it = getWaitlist.begin(); w_it != w_end; w_it++) {
|
1700
|
-
const GetWaiter &waiter = *w_it;
|
1701
|
-
result << "<item>";
|
1702
|
-
result << "<app_group_name>" << escapeForXml(waiter.options.getAppGroupName()) << "</app_group_name>";
|
1703
|
-
result << "</item>";
|
1704
|
-
}
|
1705
|
-
result << "</get_wait_list>";
|
1706
|
-
}
|
1707
|
-
|
1708
|
-
result << "<supergroups>";
|
1709
|
-
while (*sg_it != NULL) {
|
1710
|
-
const SuperGroupPtr &superGroup = sg_it.getValue();
|
1711
|
-
|
1712
|
-
result << "<supergroup>";
|
1713
|
-
result << "<name>" << escapeForXml(superGroup->name) << "</name>";
|
1714
|
-
result << "<state>" << superGroup->getStateName() << "</state>";
|
1715
|
-
result << "<get_wait_list_size>" << superGroup->getWaitlist.size() << "</get_wait_list_size>";
|
1716
|
-
result << "<capacity_used>" << superGroup->capacityUsed() << "</capacity_used>";
|
1717
|
-
if (includeSecrets) {
|
1718
|
-
result << "<secret>" << escapeForXml(superGroup->secret) << "</secret>";
|
1719
|
-
}
|
1720
|
-
|
1721
|
-
for (g_it = superGroup->groups.begin(); g_it != superGroup->groups.end(); g_it++) {
|
1722
|
-
const GroupPtr &group = *g_it;
|
1723
|
-
|
1724
|
-
if (group->componentInfo.isDefault) {
|
1725
|
-
result << "<group default=\"true\">";
|
1726
|
-
} else {
|
1727
|
-
result << "<group>";
|
1728
|
-
}
|
1729
|
-
group->inspectXml(result, includeSecrets);
|
1730
|
-
result << "</group>";
|
1731
|
-
}
|
1732
|
-
result << "</supergroup>";
|
1733
|
-
|
1734
|
-
sg_it.next();
|
1735
|
-
}
|
1736
|
-
result << "</supergroups>";
|
1737
|
-
|
1738
|
-
result << "</info>";
|
1739
|
-
return result.str();
|
1740
|
-
}
|
1741
1012
|
};
|
1742
1013
|
|
1743
1014
|
|