passenger 5.0.25 → 5.0.26
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 +4 -4
- data/CHANGELOG +20 -0
- data/CONTRIBUTORS +1 -0
- data/build/cxx_dependency_map.rb +7338 -7104
- data/build/cxx_tests.rb +3 -3
- data/build/misc.rb +1 -0
- data/dev/index_cxx_dependencies.rb +3 -2
- data/resources/templates/standalone/config.erb +1 -1
- data/resources/templates/standalone/http.erb +1 -0
- data/resources/templates/standalone/server.erb +1 -0
- data/src/agent/Core/ApplicationPool/AbstractSession.h +83 -0
- data/src/agent/Core/ApplicationPool/Common.h +6 -4
- data/src/agent/Core/ApplicationPool/Options.h +4 -1
- data/src/agent/Core/ApplicationPool/Pool.h +2 -2
- data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +3 -6
- data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
- data/src/agent/Core/ApplicationPool/Session.h +15 -27
- data/src/agent/Core/ApplicationPool/TestSession.h +188 -0
- data/src/agent/Core/Controller.h +15 -6
- data/src/agent/Core/Controller/CheckoutSession.cpp +13 -5
- data/src/agent/Core/Controller/ForwardResponse.cpp +20 -2
- data/src/agent/Core/Controller/Hooks.cpp +15 -2
- data/src/agent/Core/Controller/InitRequest.cpp +5 -1
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
- data/src/agent/Core/Controller/Request.h +11 -4
- data/src/agent/Core/Controller/SendRequest.cpp +34 -13
- data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +2 -2
- data/src/agent/Core/CoreMain.cpp +27 -1
- data/src/agent/Core/OptionParser.h +11 -1
- data/src/agent/Core/SpawningKit/DirectSpawner.h +1 -0
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -0
- data/src/agent/Core/SpawningKit/Spawner.h +21 -1
- data/src/agent/SpawnPreparer/SpawnPreparerMain.cpp +1 -1
- data/src/agent/UstRouter/OptionParser.h +7 -1
- data/src/agent/UstRouter/UstRouterMain.cpp +27 -1
- data/src/cxx_supportlib/Algorithms/MovingAverage.h +223 -0
- data/src/cxx_supportlib/Constants.h +2 -2
- data/src/cxx_supportlib/DataStructures/StringKeyTable.h +96 -40
- data/src/cxx_supportlib/ResourceLocator.h +33 -14
- data/src/cxx_supportlib/ServerKit/Channel.h +198 -69
- data/src/cxx_supportlib/ServerKit/Errors.h +6 -1
- data/src/cxx_supportlib/ServerKit/HttpRequest.h +20 -1
- data/src/cxx_supportlib/ServerKit/HttpServer.h +124 -32
- data/src/cxx_supportlib/ServerKit/Server.h +65 -1
- data/src/cxx_supportlib/Utils/IOUtils.cpp +12 -22
- data/src/cxx_supportlib/Utils/JsonUtils.h +87 -1
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +16 -1
- data/src/cxx_supportlib/Utils/StrIntUtils.h +31 -1
- data/src/cxx_supportlib/Utils/VariantMap.h +6 -1
- data/src/cxx_supportlib/WatchdogLauncher.h +17 -9
- data/src/cxx_supportlib/vendor-copy/libuv/AUTHORS +43 -0
- data/src/cxx_supportlib/vendor-copy/libuv/ChangeLog +350 -1
- data/src/cxx_supportlib/vendor-copy/libuv/Makefile.am +9 -1
- data/src/cxx_supportlib/vendor-copy/libuv/README.md +48 -0
- data/src/cxx_supportlib/vendor-copy/libuv/checksparse.sh +1 -0
- data/src/cxx_supportlib/vendor-copy/libuv/common.gypi +5 -5
- data/src/cxx_supportlib/vendor-copy/libuv/configure.ac +2 -1
- data/src/cxx_supportlib/vendor-copy/libuv/gyp_uv.py +0 -3
- data/src/cxx_supportlib/vendor-copy/libuv/include/uv-version.h +5 -1
- data/src/cxx_supportlib/vendor-copy/libuv/include/uv.h +30 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/fs-poll.c +3 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/inet.c +0 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/queue.h +17 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/threadpool.c +10 -10
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/aix.c +84 -166
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/android-ifaddrs.c +11 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/async.c +7 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/atomic-ops.h +17 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/core.c +140 -21
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin.c +15 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/dl.c +4 -7
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/freebsd.c +52 -37
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fs.c +181 -60
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fsevents.c +39 -34
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/getaddrinfo.c +4 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/internal.h +3 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/kqueue.c +12 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-core.c +38 -15
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-inotify.c +36 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.c +4 -4
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.h +2 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop-watcher.c +6 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop.c +28 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/netbsd.c +18 -16
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/openbsd.c +18 -16
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pipe.c +3 -3
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/process.c +18 -6
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/proctitle.c +2 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pthread-fixes.c +1 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/signal.c +2 -0
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/stream.c +47 -30
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sunos.c +13 -11
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tcp.c +43 -8
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/thread.c +21 -15
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tty.c +16 -2
- data/src/cxx_supportlib/vendor-copy/libuv/src/unix/udp.c +54 -14
- data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.c +104 -21
- data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.h +14 -1
- data/src/cxx_supportlib/vendor-copy/libuv/src/version.c +1 -5
- data/src/cxx_supportlib/vendor-copy/libuv/uv.gyp +22 -1
- data/src/nginx_module/CacheLocationConfig.c +52 -0
- data/src/nginx_module/CacheLocationConfig.c.erb +13 -1
- data/src/nginx_module/Configuration.c +1 -0
- data/src/nginx_module/Configuration.h +1 -0
- data/src/nginx_module/ConfigurationCommands.c +20 -0
- data/src/nginx_module/ConfigurationFields.h +4 -0
- data/src/nginx_module/CreateLocationConfig.c +8 -0
- data/src/nginx_module/MergeLocationConfig.c +12 -0
- data/src/nginx_module/config +31 -13
- data/src/nginx_module/ngx_http_passenger_module.c +4 -0
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +11 -1
- data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +6 -1
- data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +32 -31
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +13 -2
- data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +6 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +6 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +29 -19
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +2 -3
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +2 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/spec_helper.rb +2 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/time_point.rb +3 -17
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +7 -10
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +11 -9
- metadata +5 -2
@@ -60,6 +60,7 @@ private:
|
|
60
60
|
string docDir;
|
61
61
|
string rubyLibDir;
|
62
62
|
string nodeLibDir;
|
63
|
+
string buildSystemDir;
|
63
64
|
|
64
65
|
static string getOption(const string &file, const IniFileSectionPtr §ion, const string &key) {
|
65
66
|
if (section->hasKey(key)) {
|
@@ -69,13 +70,20 @@ private:
|
|
69
70
|
}
|
70
71
|
}
|
71
72
|
|
73
|
+
static string getOptionalSection(const string &file, const IniFileSectionPtr §ion, const string &key) {
|
74
|
+
if (section->hasKey(key)) {
|
75
|
+
return section->get(key);
|
76
|
+
} else {
|
77
|
+
return string();
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
72
81
|
public:
|
73
82
|
ResourceLocator() { }
|
74
83
|
|
75
|
-
ResourceLocator(const string &
|
76
|
-
|
77
|
-
|
78
|
-
string file = rootOrFile;
|
84
|
+
ResourceLocator(const string &installSpec) {
|
85
|
+
if (getFileType(installSpec) == FT_REGULAR) {
|
86
|
+
const string &file = installSpec;
|
79
87
|
IniFileSectionPtr options = IniFile(file).section("locations");
|
80
88
|
binDir = getOption(file, options, "bin_dir");
|
81
89
|
supportBinariesDir = getOption(file, options, "support_binaries_dir");
|
@@ -84,8 +92,9 @@ public:
|
|
84
92
|
docDir = getOption(file, options, "doc_dir");
|
85
93
|
rubyLibDir = getOption(file, options, "ruby_libdir");
|
86
94
|
nodeLibDir = getOption(file, options, "node_libdir");
|
95
|
+
buildSystemDir = getOptionalSection(file, options, "node_libdir");
|
87
96
|
} else {
|
88
|
-
string root =
|
97
|
+
const string &root = installSpec;
|
89
98
|
binDir = root + "/bin";
|
90
99
|
supportBinariesDir = root + "/buildout/support-binaries";
|
91
100
|
helperScriptsDir = root + "/src/helper-scripts";
|
@@ -93,14 +102,19 @@ public:
|
|
93
102
|
docDir = root + "/doc";
|
94
103
|
rubyLibDir = root + "/src/ruby_supportlib";
|
95
104
|
nodeLibDir = root + "/src/nodejs_supportlib";
|
105
|
+
buildSystemDir = root;
|
96
106
|
}
|
97
107
|
}
|
98
108
|
|
99
|
-
string getRoot() const {
|
109
|
+
const string &getRoot() const {
|
100
110
|
return root;
|
101
111
|
}
|
102
112
|
|
103
|
-
string
|
113
|
+
const string &getBinDir() const {
|
114
|
+
return binDir;
|
115
|
+
}
|
116
|
+
|
117
|
+
const string &getSupportBinariesDir() const {
|
104
118
|
return supportBinariesDir;
|
105
119
|
}
|
106
120
|
|
@@ -132,27 +146,31 @@ public:
|
|
132
146
|
return result;
|
133
147
|
}
|
134
148
|
|
135
|
-
string getHelperScriptsDir() const {
|
149
|
+
const string &getHelperScriptsDir() const {
|
136
150
|
return helperScriptsDir;
|
137
151
|
}
|
138
152
|
|
139
|
-
string getResourcesDir() const {
|
153
|
+
const string &getResourcesDir() const {
|
140
154
|
return resourcesDir;
|
141
155
|
}
|
142
156
|
|
143
|
-
string getDocDir() const {
|
157
|
+
const string &getDocDir() const {
|
144
158
|
return docDir;
|
145
159
|
}
|
146
160
|
|
147
|
-
|
148
|
-
string getRubyLibDir() const {
|
161
|
+
const string &getRubyLibDir() const {
|
149
162
|
return rubyLibDir;
|
150
163
|
}
|
151
164
|
|
152
|
-
string getNodeLibDir() const {
|
165
|
+
const string &getNodeLibDir() const {
|
153
166
|
return nodeLibDir;
|
154
167
|
}
|
155
168
|
|
169
|
+
// Can be empty.
|
170
|
+
const string &getBuildSystemDir() const {
|
171
|
+
return buildSystemDir;
|
172
|
+
}
|
173
|
+
|
156
174
|
string findSupportBinary(const string &name) {
|
157
175
|
string path = getSupportBinariesDir() + "/" + name;
|
158
176
|
bool found;
|
@@ -170,7 +188,8 @@ public:
|
|
170
188
|
return path;
|
171
189
|
}
|
172
190
|
|
173
|
-
throw RuntimeException("Support binary " + name + " not found (tried: "
|
191
|
+
throw RuntimeException("Support binary " + name + " not found (tried: "
|
192
|
+
+ getSupportBinariesDir() + "/" + name + " and " + path + ")");
|
174
193
|
}
|
175
194
|
};
|
176
195
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2014 Phusion Holding B.V.
|
3
|
+
* Copyright (c) 2014-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
5
|
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
6
|
* trademarks of Phusion Holding B.V.
|
@@ -58,8 +58,20 @@ using namespace boost;
|
|
58
58
|
*
|
59
59
|
* Writing all this code is complicated, error-prone, its flow is hard to test (because
|
60
60
|
* it depends on network conditions), and it's ridden with boilerplate. The Channel class
|
61
|
-
* solves this problem with a nice abstraction.
|
62
|
-
*
|
61
|
+
* solves this problem with a nice abstraction. A Channel is used in combination with a
|
62
|
+
* callback. Channel allows you to:
|
63
|
+
*
|
64
|
+
* - Pass data to the callback, which can consume the data at its own pace.
|
65
|
+
* - Be notified when the data has fully consumed by the callback.
|
66
|
+
* - Be notified when the callback is refusing to consume further data (e.g. because
|
67
|
+
* it is done consuming or because it has encountered an error).
|
68
|
+
* - Pass error conditions to the callback.
|
69
|
+
*
|
70
|
+
*
|
71
|
+
* ## Typical usage
|
72
|
+
*
|
73
|
+
* First, you attach a data callback to a Channel. Whatever is written to the Channel
|
74
|
+
* will be forwarded to the data callback.
|
63
75
|
*
|
64
76
|
* The data callback can consume the buffer immediately, and tell Channel how many bytes
|
65
77
|
* it has consumed, and whether it accepts any further data, by returning a Channel::Result.
|
@@ -131,11 +143,21 @@ using namespace boost;
|
|
131
143
|
* {
|
132
144
|
* if (buffer.size() > 0) {
|
133
145
|
* int bytesProcessed;
|
146
|
+
* int errcode;
|
134
147
|
* bool acceptFurtherData;
|
135
148
|
*
|
136
149
|
* ...process buffer....
|
137
150
|
*
|
138
|
-
*
|
151
|
+
* if (errcode == 0) {
|
152
|
+
* // Everything OK.
|
153
|
+
* return Channel::Result(bytesProcessed, !acceptFurtherData);
|
154
|
+
* } else {
|
155
|
+
* // An error occurred.
|
156
|
+
* feedError(errcode);
|
157
|
+
* // If you called feedError() then it doesn't matter what
|
158
|
+
* // you return.
|
159
|
+
* return Channel::Result(0, false);
|
160
|
+
* }
|
139
161
|
* } else if (errcode == 0) {
|
140
162
|
* // EOF reached. Result doesn't matter in this case.
|
141
163
|
* return Channel::Result(0, false);
|
@@ -146,12 +168,66 @@ using namespace boost;
|
|
146
168
|
* }
|
147
169
|
* }
|
148
170
|
*
|
149
|
-
*
|
171
|
+
* ### Recommended example: FdSourceChannel
|
172
|
+
*
|
173
|
+
* A good example is FdSourceChannel. It reads data from a file descriptor using
|
150
174
|
* `read()`, then writes them to a Channel. It stops reading from the file descriptor
|
151
175
|
* when the Channel is not accepting reads, and it starts reading from the file
|
152
176
|
* descriptor when the channel is accepting reads again.
|
153
177
|
*
|
154
|
-
*
|
178
|
+
*
|
179
|
+
* ## The data callback
|
180
|
+
*
|
181
|
+
* The data callback is called when the Channel wants to pass data to the callback,
|
182
|
+
* or when the channel wants to notify the callback of an error.
|
183
|
+
*
|
184
|
+
* ### Arguments
|
185
|
+
*
|
186
|
+
* - `channel` -- the Channel object that called it.
|
187
|
+
* - `buffer` -- a buffer containing data. This buffer may be empty because
|
188
|
+
* the writer called `channel.feed()` with an empty buffer, or because of
|
189
|
+
* an error.
|
190
|
+
* - `error` -- an error code. A value of 0 means that there is no error. All
|
191
|
+
* other values indicate an error.
|
192
|
+
*
|
193
|
+
* If an error occurred then the buffer is always empty. If the buffer is non-empty
|
194
|
+
* then errcode is always zero.
|
195
|
+
*
|
196
|
+
* Be sure to check for errors correctly: you may only use `buffer` if `errcode` is 0.
|
197
|
+
*
|
198
|
+
* ### Returning consumption result
|
199
|
+
*
|
200
|
+
* The data callback is to return a `Channel::Result` object in order to tell Channel
|
201
|
+
* how many bytes have been consumed (the `consumed` field), and whether it accepts
|
202
|
+
* further data (the `end` field).
|
203
|
+
*
|
204
|
+
* Returning `end == true` will set the Channel to the "end acknowledged" state. This
|
205
|
+
* causes the Channel to stop accepting and/or forwarding further data or error to the
|
206
|
+
* callback (even if there is pending unconsumed data). The writer can detect this state
|
207
|
+
* by calling:
|
208
|
+
*
|
209
|
+
* - `channel.acceptingInput()` -- will return false.
|
210
|
+
* - `channel.mayAcceptInputLater()` -- will return false.
|
211
|
+
* - `channel.ended()` -- will return true.
|
212
|
+
* - `channel.endAcked()` -- will return true.
|
213
|
+
* - `channel.hasError()` -- will return false.
|
214
|
+
*
|
215
|
+
* ### Returning error result
|
216
|
+
*
|
217
|
+
* The data callback can tell the Channel that an error during consumption has occurred
|
218
|
+
* by calling `channel.feedError()` with a non-zero error code. Once `feedError()` has
|
219
|
+
* been called, it doesn't matter what the data callback returns: anything is fine.
|
220
|
+
* The Channel will enter the "end acknowledged with error" state and/or will stop
|
221
|
+
* forwarding further data or error to the callback (even if there is pending unconsumed
|
222
|
+
* data). The writer will observe:
|
223
|
+
*
|
224
|
+
* - `channel.acceptingInput()` -- will return false.
|
225
|
+
* - `channel.mayAcceptInputLater()` -- will return false.
|
226
|
+
* - `channel.ended()` -- will return true.
|
227
|
+
* - `channel.endAcked()` -- will return true.
|
228
|
+
* - `channel.hasError()` -- will return true.
|
229
|
+
*
|
230
|
+
* ### Asynchronous consumption
|
155
231
|
*
|
156
232
|
* The data callback can also tell Channel that it wants to consume the buffer
|
157
233
|
* *asynchronously*, by returning a Channel::Result with a negative consumption size.
|
@@ -159,7 +235,22 @@ using namespace boost;
|
|
159
235
|
* by calling `channel.consumed()`. Until that happens, the Channel will tell the
|
160
236
|
* writer that it is not accepting any new data, so that the writer can stop writing
|
161
237
|
* temporarily. When the buffer is consumed, the Channel notifies the writer about
|
162
|
-
* this so that it can continue writing.
|
238
|
+
* this (via `consumedCallback`) so that it can continue writing.
|
239
|
+
*
|
240
|
+
* The arguments passed to `channel.consumed()` are the same as those used to create
|
241
|
+
* a `Channel::Result`. The `size` arguments tells Channel how many bytes have been
|
242
|
+
* consumed. The `end` argument tells whether the callback is done consuming.
|
243
|
+
*
|
244
|
+
* If Channel has no further pending data to be passed to the callback, then Channel
|
245
|
+
* immediately calls `consumedCallback`. Otherwise, Channel will pass the remaining
|
246
|
+
* data in the next event loop iteration.
|
247
|
+
*
|
248
|
+
* ### Asynchronous consumption error reporting
|
249
|
+
*
|
250
|
+
* If you are using asynchronous consumption (by returning a Channel::Result with a
|
251
|
+
* negative consumption size) then the way to signal a consumption error is by calling
|
252
|
+
* `channel.feedError()` instead of calling `channel.consumed()`. This will cause the
|
253
|
+
* channel to immediately enter the "end acknowledged with error" state.
|
163
254
|
*/
|
164
255
|
class Channel: public boost::noncopyable {
|
165
256
|
public:
|
@@ -232,19 +323,20 @@ public:
|
|
232
323
|
* An end-of-file or error has been passed to the callback, and we're
|
233
324
|
* now waiting for the callback to return.
|
234
325
|
*/
|
235
|
-
|
326
|
+
CALLING_WITH_EOF_OR_ERROR,
|
236
327
|
|
237
328
|
/**
|
238
329
|
* An end-of-file or error has been passed to the callback, but the
|
239
|
-
* callback hasn't called `consumed()` yet.
|
330
|
+
* callback hasn't called `consumed()` yet. We're now waiting for
|
331
|
+
* that call.
|
240
332
|
*/
|
241
|
-
|
333
|
+
WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR,
|
242
334
|
|
243
335
|
/**
|
244
336
|
* An end-of-file or error has been passed to the callback, and the
|
245
337
|
* callback has returned and completed.
|
246
338
|
*/
|
247
|
-
|
339
|
+
EOF_OR_ERROR_ACKNOWLEDGED
|
248
340
|
};
|
249
341
|
|
250
342
|
protected:
|
@@ -270,9 +362,9 @@ protected:
|
|
270
362
|
|
271
363
|
begin:
|
272
364
|
|
273
|
-
assert(state == CALLING || state ==
|
365
|
+
assert(state == CALLING || state == CALLING_WITH_EOF_OR_ERROR);
|
274
366
|
assert(state != CALLING || !buffer.empty());
|
275
|
-
assert(state !=
|
367
|
+
assert(state != CALLING_WITH_EOF_OR_ERROR || buffer.empty());
|
276
368
|
|
277
369
|
{
|
278
370
|
// Make a copy of the buffer so that if the callback calls
|
@@ -291,7 +383,7 @@ protected:
|
|
291
383
|
assert(state != STOPPED);
|
292
384
|
assert(state != STOPPED_WHILE_WAITING);
|
293
385
|
assert(state != PLANNING_TO_CALL);
|
294
|
-
assert(state !=
|
386
|
+
assert(state != WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR);
|
295
387
|
|
296
388
|
if (cbResult.consumed >= 0) {
|
297
389
|
bytesConsumed += cbResult.consumed;
|
@@ -305,7 +397,7 @@ protected:
|
|
305
397
|
switch (state) {
|
306
398
|
case CALLING:
|
307
399
|
if (cbResult.end) {
|
308
|
-
state =
|
400
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
309
401
|
callConsumedCallback();
|
310
402
|
return bytesConsumed;
|
311
403
|
} else if (buffer.empty()) {
|
@@ -325,21 +417,20 @@ protected:
|
|
325
417
|
}
|
326
418
|
case STOPPED_WHILE_CALLING:
|
327
419
|
if (cbResult.end) {
|
328
|
-
state =
|
420
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
329
421
|
callConsumedCallback();
|
330
422
|
return bytesConsumed;
|
331
423
|
} else {
|
332
424
|
state = STOPPED;
|
333
425
|
return -1;
|
334
426
|
}
|
335
|
-
case
|
336
|
-
state =
|
427
|
+
case CALLING_WITH_EOF_OR_ERROR:
|
428
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
337
429
|
callConsumedCallback();
|
338
430
|
return bytesConsumed;
|
339
|
-
case
|
431
|
+
case EOF_OR_ERROR_ACKNOWLEDGED:
|
340
432
|
// feedError() called inside callback, so we
|
341
433
|
// don't callConsumedCallback() here.
|
342
|
-
state = EOF_REACHED;
|
343
434
|
return bytesConsumed;
|
344
435
|
default:
|
345
436
|
P_BUG("Unknown state" << toString((int) state));
|
@@ -354,9 +445,9 @@ protected:
|
|
354
445
|
case STOPPED_WHILE_CALLING:
|
355
446
|
state = STOPPED_WHILE_WAITING;
|
356
447
|
break;
|
357
|
-
case
|
358
|
-
case
|
359
|
-
state =
|
448
|
+
case CALLING_WITH_EOF_OR_ERROR:
|
449
|
+
case EOF_OR_ERROR_ACKNOWLEDGED:
|
450
|
+
state = WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR;
|
360
451
|
break;
|
361
452
|
default:
|
362
453
|
P_BUG("Unknown state" << toString((int) state));
|
@@ -407,7 +498,7 @@ public:
|
|
407
498
|
* you call `setContext()`.
|
408
499
|
*/
|
409
500
|
Channel()
|
410
|
-
: state(
|
501
|
+
: state(EOF_OR_ERROR_ACKNOWLEDGED),
|
411
502
|
planId(0),
|
412
503
|
errcode(0),
|
413
504
|
generation(0),
|
@@ -473,7 +564,8 @@ public:
|
|
473
564
|
}
|
474
565
|
|
475
566
|
/**
|
476
|
-
* Feed data to the Channel. The data will be passed to the callback.
|
567
|
+
* Feed data to the Channel. The data will be passed to the callback. You can signal
|
568
|
+
* EOF by feeding an empty buffer.
|
477
569
|
*
|
478
570
|
* @pre acceptingInput()
|
479
571
|
*/
|
@@ -503,7 +595,7 @@ public:
|
|
503
595
|
P_ASSERT_EQ(state, IDLE);
|
504
596
|
P_ASSERT_EQ(bytesConsumed, 0);
|
505
597
|
if (mbuf.empty()) {
|
506
|
-
state =
|
598
|
+
state = CALLING_WITH_EOF_OR_ERROR;
|
507
599
|
} else {
|
508
600
|
state = CALLING;
|
509
601
|
}
|
@@ -514,37 +606,54 @@ public:
|
|
514
606
|
/**
|
515
607
|
* Tell the Channel that an error has occurred.
|
516
608
|
*
|
517
|
-
*
|
518
|
-
*
|
519
|
-
*
|
520
|
-
*
|
609
|
+
* This method can be called with two purposes. You can either use it to
|
610
|
+
* pass an error to the data callback, or you can use it to register an
|
611
|
+
* error that occurred inside the data callback (a consumption error).
|
612
|
+
*
|
613
|
+
* ## Passing an error to the data callback
|
614
|
+
*
|
615
|
+
* If you want to pass an error to the data callback then you can only do that
|
616
|
+
* when `acceptingInput()` is true. Calling `feedError()` in this state will
|
617
|
+
* call the data callback immediately.
|
618
|
+
*
|
619
|
+
* ## Registering a consumption error
|
620
|
+
*
|
621
|
+
* The data callback can tell the Channel about a consumption error by calling
|
622
|
+
* this method inside the data callback, or (if the data callback is using
|
623
|
+
* asynchronous consumption by having returned -1) by calling this method
|
624
|
+
* in place of `consumed()`.
|
521
625
|
*
|
522
|
-
*
|
523
|
-
* when the data callback hasn't called `consumed()` yet, then the channel transitions
|
524
|
-
* to the end state immediately, and stops calling the data callback even when the
|
525
|
-
* current invocation of the data callback doesn't fully consume the buffer.
|
626
|
+
* ## Effect
|
526
627
|
*
|
527
|
-
*
|
628
|
+
* In both of the above cases, the Channel will begin transitioning to an end error state:
|
629
|
+
*
|
630
|
+
* acceptingInput() -- will return false.
|
631
|
+
* mayAcceptInputLater() -- will return false.
|
632
|
+
* ended() -- will return true.
|
633
|
+
* endAcked() -- depending on the situation, will return true immediately,
|
634
|
+
* or will return true eventually.
|
635
|
+
* hasError() -- will return true.
|
636
|
+
*
|
637
|
+
* No more data will be accepted by `feed()`.
|
528
638
|
*/
|
529
639
|
void feedError(int errcode) {
|
530
640
|
assert(errcode != 0);
|
531
641
|
switch (state) {
|
532
642
|
case IDLE:
|
533
643
|
this->errcode = errcode;
|
534
|
-
state =
|
644
|
+
state = CALLING_WITH_EOF_OR_ERROR;
|
535
645
|
callDataCallback();
|
536
646
|
break;
|
537
647
|
case CALLING:
|
538
648
|
case WAITING_FOR_CALLBACK:
|
539
|
-
case
|
540
|
-
case
|
649
|
+
case CALLING_WITH_EOF_OR_ERROR:
|
650
|
+
case WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR:
|
541
651
|
this->errcode = errcode;
|
542
|
-
state =
|
652
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
543
653
|
callConsumedCallback();
|
544
654
|
break;
|
545
|
-
case
|
655
|
+
case EOF_OR_ERROR_ACKNOWLEDGED:
|
546
656
|
this->errcode = errcode;
|
547
|
-
state = EOF_REACHED;
|
548
657
|
break;
|
549
658
|
case STOPPED:
|
550
659
|
case STOPPED_WHILE_CALLING:
|
@@ -556,7 +665,7 @@ public:
|
|
556
665
|
ctx->libev->cancelCommand(planId);
|
557
666
|
planId = 0;
|
558
667
|
this->errcode = errcode;
|
559
|
-
state =
|
668
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
560
669
|
callConsumedCallback();
|
561
670
|
break;
|
562
671
|
default:
|
@@ -574,9 +683,9 @@ public:
|
|
574
683
|
case CALLING:
|
575
684
|
case PLANNING_TO_CALL:
|
576
685
|
case WAITING_FOR_CALLBACK:
|
577
|
-
case
|
578
|
-
case
|
579
|
-
case
|
686
|
+
case CALLING_WITH_EOF_OR_ERROR:
|
687
|
+
case WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR:
|
688
|
+
case EOF_OR_ERROR_ACKNOWLEDGED:
|
580
689
|
break;
|
581
690
|
case STOPPED:
|
582
691
|
planNextActivity();
|
@@ -602,9 +711,9 @@ public:
|
|
602
711
|
case STOPPED:
|
603
712
|
case STOPPED_WHILE_CALLING:
|
604
713
|
case STOPPED_WHILE_WAITING:
|
605
|
-
case
|
606
|
-
case
|
607
|
-
case
|
714
|
+
case CALLING_WITH_EOF_OR_ERROR:
|
715
|
+
case WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR:
|
716
|
+
case EOF_OR_ERROR_ACKNOWLEDGED:
|
608
717
|
break;
|
609
718
|
case IDLE:
|
610
719
|
case PLANNING_TO_CALL:
|
@@ -636,8 +745,8 @@ public:
|
|
636
745
|
assert(state != STOPPED);
|
637
746
|
assert(state != STOPPED_WHILE_CALLING);
|
638
747
|
assert(state != PLANNING_TO_CALL);
|
639
|
-
assert(state !=
|
640
|
-
assert(state !=
|
748
|
+
assert(state != CALLING_WITH_EOF_OR_ERROR);
|
749
|
+
assert(state != EOF_OR_ERROR_ACKNOWLEDGED);
|
641
750
|
|
642
751
|
size = std::min<unsigned int>(size, buffer.size());
|
643
752
|
bytesConsumed += size;
|
@@ -651,7 +760,7 @@ public:
|
|
651
760
|
switch (state) {
|
652
761
|
case WAITING_FOR_CALLBACK:
|
653
762
|
if (end) {
|
654
|
-
state =
|
763
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
655
764
|
callConsumedCallback();
|
656
765
|
} else {
|
657
766
|
planNextActivity();
|
@@ -659,14 +768,14 @@ public:
|
|
659
768
|
break;
|
660
769
|
case STOPPED_WHILE_WAITING:
|
661
770
|
if (end) {
|
662
|
-
state =
|
771
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
663
772
|
callConsumedCallback();
|
664
773
|
} else {
|
665
774
|
state = STOPPED;
|
666
775
|
}
|
667
776
|
break;
|
668
|
-
case
|
669
|
-
state =
|
777
|
+
case WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR:
|
778
|
+
state = EOF_OR_ERROR_ACKNOWLEDGED;
|
670
779
|
callConsumedCallback();
|
671
780
|
break;
|
672
781
|
default:
|
@@ -693,10 +802,13 @@ public:
|
|
693
802
|
* Returns whether this Channel accepts more input right now.
|
694
803
|
* There are three reasons why this might not be the case:
|
695
804
|
*
|
696
|
-
* 1. The callback isn't done yet
|
697
|
-
*
|
698
|
-
*
|
699
|
-
*
|
805
|
+
* 1. The callback isn't done yet, or the callback is done but the Channel
|
806
|
+
* isn't done updating internal book keeping yet. Use `mayAcceptInputLater()`
|
807
|
+
* to check for this.
|
808
|
+
* 2. EOF has been fed (by passing an empty buffer to `feed()`), or the data callback
|
809
|
+
* has ended consumption (by returning a Channel::Result with end == true, or by calling
|
810
|
+
* consumed() with end == true). Use `ended()` to check for this.
|
811
|
+
* 3. An error had been fed (using `feedError()`). Use `hasError()` to check for this.
|
700
812
|
*/
|
701
813
|
OXT_FORCE_INLINE
|
702
814
|
bool acceptingInput() const {
|
@@ -705,9 +817,9 @@ public:
|
|
705
817
|
|
706
818
|
/**
|
707
819
|
* Returns whether this Channel's callback is currently processing the
|
708
|
-
* fed data, and is not accepting any more input now,
|
709
|
-
*
|
710
|
-
* `consumedCallback`.
|
820
|
+
* fed data, and is not accepting any more input now. However, no EOF or
|
821
|
+
* error has been reported so far, so it may accept more input later. You
|
822
|
+
* should wait for that event by setting `consumedCallback`.
|
711
823
|
*/
|
712
824
|
bool mayAcceptInputLater() const {
|
713
825
|
// Branchless code
|
@@ -715,9 +827,15 @@ public:
|
|
715
827
|
}
|
716
828
|
|
717
829
|
/**
|
718
|
-
* Returns whether an error flag has been set.
|
719
|
-
*
|
720
|
-
*
|
830
|
+
* Returns whether an error flag has been set. This happens if `feedError()`
|
831
|
+
* was called.
|
832
|
+
*
|
833
|
+
* `hasError()` always implies `end()`.
|
834
|
+
*
|
835
|
+
* Note that `hasError()` does not necessarily mean that the callback has
|
836
|
+
* consumed the error yet. The callback may be called at a later time to
|
837
|
+
* notify it about the error. When the callback is done consuming the error,
|
838
|
+
* `hasError() && endAcked()` will be true.
|
721
839
|
*/
|
722
840
|
OXT_FORCE_INLINE
|
723
841
|
bool hasError() const {
|
@@ -730,17 +848,28 @@ public:
|
|
730
848
|
}
|
731
849
|
|
732
850
|
/**
|
733
|
-
* Returns whether the EOF flag has been set.
|
734
|
-
*
|
735
|
-
*
|
851
|
+
* Returns whether the EOF flag has been set. This happens if `feed()` was
|
852
|
+
* called with an empty buffer.
|
853
|
+
*
|
854
|
+
* Note that this does not necessarily mean that the callback has consumed
|
855
|
+
* the EOF yet. The callback may be called at a later time to notify it about
|
856
|
+
* the EOF event. When the callback is done consuming the EOF event, `endAcked()`
|
857
|
+
* will be true.
|
736
858
|
*/
|
737
859
|
bool ended() const {
|
738
|
-
return state ==
|
860
|
+
return state == CALLING_WITH_EOF_OR_ERROR
|
861
|
+
|| state == WAITING_FOR_CALLBACK_WITH_EOF_OR_ERROR
|
862
|
+
|| state == EOF_OR_ERROR_ACKNOWLEDGED;
|
739
863
|
}
|
740
864
|
|
865
|
+
/**
|
866
|
+
* Returns whether the data callback has consumed an EOF event.
|
867
|
+
*
|
868
|
+
* `endAcked()` always implies `ended()`.
|
869
|
+
*/
|
741
870
|
OXT_FORCE_INLINE
|
742
871
|
bool endAcked() const {
|
743
|
-
return state ==
|
872
|
+
return state == EOF_OR_ERROR_ACKNOWLEDGED;
|
744
873
|
}
|
745
874
|
|
746
875
|
Json::Value inspectAsJson() const {
|