passenger 4.0.2 → 4.0.3
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.
- data.tar.gz.asc +7 -7
- data/NEWS +27 -0
- data/bin/passenger-config +6 -3
- data/bin/passenger-install-apache2-module +2 -2
- data/bin/passenger-install-nginx-module +16 -2
- data/build/agents.rb +4 -0
- data/build/apache2.rb +1 -1
- data/build/cplusplus_support.rb +1 -1
- data/build/cxx_tests.rb +3 -0
- data/build/packaging.rb +51 -8
- data/build/ruby_extension.rb +1 -1
- data/doc/Packaging.txt.md +20 -7
- data/doc/Users guide Apache.html +1 -1
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +5 -4
- data/doc/Users guide Nginx.txt +1 -1
- data/doc/users_guide_snippets/installation.txt +5 -3
- data/ext/apache2/Configuration.cpp +12 -0
- data/ext/apache2/Configuration.hpp +7 -4
- data/ext/apache2/Hooks.cpp +29 -19
- data/ext/common/AgentsStarter.cpp +85 -57
- data/ext/common/AgentsStarter.h +570 -42
- data/ext/common/ApplicationPool2/DirectSpawner.h +5 -2
- data/ext/common/ApplicationPool2/Implementation.cpp +7 -1
- data/ext/common/ApplicationPool2/Pool.h +6 -3
- data/ext/common/ApplicationPool2/Process.h +12 -3
- data/ext/common/ApplicationPool2/SmartSpawner.h +2 -1
- data/ext/common/Constants.h +4 -1
- data/ext/common/EventedBufferedInput.h +139 -16
- data/ext/common/MultiLibeio.cpp +4 -2
- data/ext/common/SafeLibev.h +15 -62
- data/ext/common/ServerInstanceDir.h +10 -26
- data/ext/common/Utils.cpp +1 -3
- data/ext/common/Utils.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +9 -0
- data/ext/common/Utils/StrIntUtils.h +5 -0
- data/ext/common/Utils/VariantMap.h +63 -14
- data/ext/common/agents/Base.cpp +50 -15
- data/ext/common/agents/HelperAgent/AgentOptions.h +20 -12
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +1 -1
- data/ext/common/agents/HelperAgent/Main.cpp +5 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
- data/ext/common/agents/LoggingAgent/Main.cpp +0 -1
- data/ext/common/agents/LoggingAgent/RemoteSender.h +2 -2
- data/ext/common/agents/SpawnPreparer.cpp +23 -5
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +508 -0
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +93 -0
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +68 -0
- data/ext/common/agents/Watchdog/Main.cpp +180 -802
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +111 -0
- data/ext/nginx/Configuration.c +107 -92
- data/ext/nginx/Configuration.h +1 -0
- data/ext/nginx/ContentHandler.c +6 -6
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +8 -2
- data/ext/nginx/ngx_http_passenger_module.c +54 -60
- data/ext/nginx/ngx_http_passenger_module.h +6 -6
- data/lib/phusion_passenger.rb +17 -10
- data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
- data/lib/phusion_passenger/common_library.rb +0 -1
- data/lib/phusion_passenger/platform_info.rb +10 -1
- data/lib/phusion_passenger/platform_info/depcheck.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +2 -2
- data/lib/phusion_passenger/platform_info/ruby.rb +7 -0
- data/lib/phusion_passenger/request_handler.rb +119 -42
- data/lib/phusion_passenger/request_handler/thread_handler.rb +25 -22
- data/lib/phusion_passenger/standalone/command.rb +2 -0
- data/lib/phusion_passenger/standalone/runtime_installer.rb +4 -3
- data/lib/phusion_passenger/standalone/start_command.rb +49 -37
- data/resources/templates/nginx/pcre_checksum_could_not_be_verified.txt.erb +11 -0
- data/test/cxx/CxxTestMain.cpp +2 -0
- data/test/cxx/EventedBufferedInputTest.cpp +758 -0
- data/test/cxx/ServerInstanceDirTest.cpp +16 -31
- data/test/cxx/TestSupport.cpp +2 -1
- data/test/cxx/VariantMapTest.cpp +23 -11
- metadata +8 -4
- metadata.gz.asc +7 -7
- data/ext/common/AgentsStarter.hpp +0 -655
- data/lib/phusion_passenger/utils/robust_interruption.rb +0 -173
data/ext/common/MultiLibeio.cpp
CHANGED
@@ -54,7 +54,9 @@ struct Data {
|
|
54
54
|
Data(const SafeLibevPtr &_libev, const MultiLibeio::Callback &_callback)
|
55
55
|
: libev(_libev),
|
56
56
|
callback(_callback)
|
57
|
-
|
57
|
+
{
|
58
|
+
assert(_libev != NULL);
|
59
|
+
}
|
58
60
|
};
|
59
61
|
|
60
62
|
struct CustomData: public Data {
|
@@ -96,7 +98,7 @@ static int
|
|
96
98
|
dispatch(eio_req *req) {
|
97
99
|
auto_ptr<Data> data((Data *) req->data);
|
98
100
|
assert(data->libev != NULL); // Check for strange bug.
|
99
|
-
data->libev->
|
101
|
+
data->libev->runLater(boost::bind(data->callback, *req));
|
100
102
|
return 0;
|
101
103
|
}
|
102
104
|
|
data/ext/common/SafeLibev.h
CHANGED
@@ -58,23 +58,9 @@ private:
|
|
58
58
|
{ }
|
59
59
|
};
|
60
60
|
|
61
|
-
struct Timer {
|
62
|
-
ev_timer realTimer;
|
63
|
-
SafeLibev *self;
|
64
|
-
Callback callback;
|
65
|
-
list<Timer *>::iterator it;
|
66
|
-
|
67
|
-
Timer(SafeLibev *_self, const Callback &_callback)
|
68
|
-
: self(_self),
|
69
|
-
callback(_callback)
|
70
|
-
{ }
|
71
|
-
};
|
72
|
-
|
73
61
|
struct ev_loop *loop;
|
74
62
|
pthread_t loopThread;
|
75
63
|
ev_async async;
|
76
|
-
ev_idle idle;
|
77
|
-
list<Timer *> timers;
|
78
64
|
|
79
65
|
boost::mutex syncher;
|
80
66
|
condition_variable cond;
|
@@ -86,17 +72,9 @@ private:
|
|
86
72
|
self->runCommands();
|
87
73
|
}
|
88
74
|
|
89
|
-
static void
|
90
|
-
|
91
|
-
|
92
|
-
}
|
93
|
-
|
94
|
-
static void timeoutHandler(EV_P_ ev_timer *t, int revents) {
|
95
|
-
auto_ptr<Timer> timer((Timer *) ((const char *) t));
|
96
|
-
SafeLibev *self = timer->self;
|
97
|
-
self->timers.erase(timer->it);
|
98
|
-
ev_timer_stop(self->loop, &timer->realTimer);
|
99
|
-
timer->callback();
|
75
|
+
static void timeoutHandler(int revents, void *arg) {
|
76
|
+
auto_ptr<Callback> callback((Callback *) arg);
|
77
|
+
(*callback)();
|
100
78
|
}
|
101
79
|
|
102
80
|
void runCommands() {
|
@@ -151,12 +129,9 @@ public:
|
|
151
129
|
nextCommandId = 0;
|
152
130
|
|
153
131
|
ev_async_init(&async, asyncHandler);
|
132
|
+
ev_set_priority(&async, EV_MAXPRI);
|
154
133
|
async.data = this;
|
155
134
|
ev_async_start(loop, &async);
|
156
|
-
|
157
|
-
ev_idle_init(&idle, idleHandler);
|
158
|
-
ev_set_priority(&idle, EV_MAXPRI);
|
159
|
-
idle.data = this;
|
160
135
|
}
|
161
136
|
|
162
137
|
~SafeLibev() {
|
@@ -166,15 +141,6 @@ public:
|
|
166
141
|
|
167
142
|
void destroy() {
|
168
143
|
ev_async_stop(loop, &async);
|
169
|
-
ev_idle_stop(loop, &idle);
|
170
|
-
|
171
|
-
list<Timer *>::iterator it, end = timers.end();
|
172
|
-
for (it = timers.begin(); it != end; it++) {
|
173
|
-
Timer *timer = *it;
|
174
|
-
ev_timer_stop(loop, &timer->realTimer);
|
175
|
-
delete timer;
|
176
|
-
}
|
177
|
-
timers.clear();
|
178
144
|
}
|
179
145
|
|
180
146
|
struct ev_loop *getLoop() const {
|
@@ -249,36 +215,23 @@ public:
|
|
249
215
|
}
|
250
216
|
}
|
251
217
|
|
252
|
-
|
253
|
-
runLaterTS(callback);
|
254
|
-
}
|
255
|
-
|
256
|
-
// TODO: make it possible to call this from a thread
|
218
|
+
/** Run a callback after a certain timeout. */
|
257
219
|
void runAfter(unsigned int timeout, const Callback &callback) {
|
258
220
|
assert(callback != NULL);
|
259
|
-
|
260
|
-
ev_timer_init(&timer->realTimer, timeoutHandler, timeout / 1000.0, 0);
|
261
|
-
timers.push_front(timer);
|
262
|
-
timer->it = timers.begin();
|
263
|
-
ev_timer_start(loop, &timer->realTimer);
|
221
|
+
ev_once(loop, -1, 0, timeout / 1000.0, timeoutHandler, new Callback(callback));
|
264
222
|
}
|
265
223
|
|
266
|
-
|
224
|
+
/** Thread-safe version of runAfter(). */
|
225
|
+
void runAfterTS(unsigned int timeout, const Callback &callback) {
|
267
226
|
assert(callback != NULL);
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
result = nextCommandId;
|
273
|
-
incNextCommandId();
|
274
|
-
}
|
275
|
-
if (!ev_is_active(&idle)) {
|
276
|
-
ev_idle_start(loop, &idle);
|
227
|
+
if (pthread_equal(pthread_self(), loopThread)) {
|
228
|
+
runAfter(timeout, callback);
|
229
|
+
} else {
|
230
|
+
runLater(boost::bind(&SafeLibev::runAfter, this, timeout, callback));
|
277
231
|
}
|
278
|
-
return result;
|
279
232
|
}
|
280
|
-
|
281
|
-
unsigned int
|
233
|
+
|
234
|
+
unsigned int runLater(const Callback &callback) {
|
282
235
|
assert(callback != NULL);
|
283
236
|
unsigned int result;
|
284
237
|
{
|
@@ -292,7 +245,7 @@ public:
|
|
292
245
|
}
|
293
246
|
|
294
247
|
/**
|
295
|
-
* Cancels a callback that was scheduled to be run by runLater()
|
248
|
+
* Cancels a callback that was scheduled to be run by runLater().
|
296
249
|
* Returns whether the command has been successfully cancelled or not.
|
297
250
|
* That is, a return value of true guarantees that the callback will not be called
|
298
251
|
* in the future, while a return value of false means that the callback has already
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2010 Phusion
|
3
|
+
* Copyright (c) 2010-2013 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -52,7 +52,7 @@ public:
|
|
52
52
|
// Don't forget to update lib/phusion_passenger/admin_tools/server_instance.rb too.
|
53
53
|
static const int DIR_STRUCTURE_MAJOR_VERSION = 1;
|
54
54
|
static const int DIR_STRUCTURE_MINOR_VERSION = 0;
|
55
|
-
static const int GENERATION_STRUCTURE_MAJOR_VERSION =
|
55
|
+
static const int GENERATION_STRUCTURE_MAJOR_VERSION = 2;
|
56
56
|
static const int GENERATION_STRUCTURE_MINOR_VERSION = 0;
|
57
57
|
|
58
58
|
class Generation: public noncopyable {
|
@@ -179,7 +179,9 @@ public:
|
|
179
179
|
return number;
|
180
180
|
}
|
181
181
|
|
182
|
-
|
182
|
+
// The 'const strng &' here is on purpose. The AgentsStarter C
|
183
|
+
// functions return the string pointer directly.
|
184
|
+
const string &getPath() const {
|
183
185
|
return path;
|
184
186
|
}
|
185
187
|
|
@@ -236,28 +238,6 @@ private:
|
|
236
238
|
}
|
237
239
|
|
238
240
|
public:
|
239
|
-
ServerInstanceDir(pid_t webServerPid, const string &parentDir = "", bool owner = true) {
|
240
|
-
string theParentDir;
|
241
|
-
|
242
|
-
if (parentDir.empty()) {
|
243
|
-
theParentDir = getSystemTempDir();
|
244
|
-
} else {
|
245
|
-
theParentDir = parentDir;
|
246
|
-
}
|
247
|
-
|
248
|
-
/* We embed the super structure version in the server instance directory name
|
249
|
-
* because it's possible to upgrade Phusion Passenger without changing the
|
250
|
-
* web server's PID. This way each incompatible upgrade will use its own
|
251
|
-
* server instance directory.
|
252
|
-
*/
|
253
|
-
initialize(theParentDir + "/passenger." +
|
254
|
-
toString(DIR_STRUCTURE_MAJOR_VERSION) + "." +
|
255
|
-
toString(DIR_STRUCTURE_MINOR_VERSION) + "." +
|
256
|
-
toString<unsigned long long>(webServerPid),
|
257
|
-
owner);
|
258
|
-
|
259
|
-
}
|
260
|
-
|
261
241
|
ServerInstanceDir(const string &path, bool owner = true) {
|
262
242
|
initialize(path, owner);
|
263
243
|
}
|
@@ -280,7 +260,9 @@ public:
|
|
280
260
|
}
|
281
261
|
}
|
282
262
|
|
283
|
-
|
263
|
+
// The 'const strng &' here is on purpose. The AgentsStarter C
|
264
|
+
// functions return the string pointer directly.
|
265
|
+
const string &getPath() const {
|
284
266
|
return path;
|
285
267
|
}
|
286
268
|
|
@@ -307,6 +289,8 @@ public:
|
|
307
289
|
}
|
308
290
|
|
309
291
|
GenerationPtr getGeneration(unsigned int number) const {
|
292
|
+
// Must not used make_shared() here because Watchdog.cpp
|
293
|
+
// deletes the raw pointer in cleanupAgentsInBackground().
|
310
294
|
return ptr(new Generation(path, number));
|
311
295
|
}
|
312
296
|
|
data/ext/common/Utils.cpp
CHANGED
@@ -712,7 +712,7 @@ verifyWSGIDir(const string &dir, CachedFileStat *cstat, unsigned int throttleRat
|
|
712
712
|
|
713
713
|
void
|
714
714
|
prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
715
|
-
const string &
|
715
|
+
const vector<string> &prestartURLs)
|
716
716
|
{
|
717
717
|
/* Apache calls the initialization routines twice during startup, and
|
718
718
|
* as a result it starts two helper servers, where the first one exits
|
@@ -724,11 +724,9 @@ prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
|
724
724
|
|
725
725
|
this_thread::disable_interruption di;
|
726
726
|
this_thread::disable_syscall_interruption dsi;
|
727
|
-
vector<string> prestartURLs;
|
728
727
|
vector<string>::const_iterator it;
|
729
728
|
string prespawnScript = locator.getHelperScriptsDir() + "/prespawn";
|
730
729
|
|
731
|
-
split(Base64::decode(serializedprestartURLs), '\0', prestartURLs);
|
732
730
|
it = prestartURLs.begin();
|
733
731
|
while (it != prestartURLs.end() && !this_thread::interruption_requested()) {
|
734
732
|
if (it->empty()) {
|
data/ext/common/Utils.h
CHANGED
@@ -366,7 +366,7 @@ bool verifyWSGIDir(const string &dir, CachedFileStat *cstat = 0,
|
|
366
366
|
unsigned int throttleRate = 0);
|
367
367
|
|
368
368
|
void prestartWebApps(const ResourceLocator &locator, const string &ruby,
|
369
|
-
const string &
|
369
|
+
const vector<string> &prestartURLs);
|
370
370
|
|
371
371
|
/**
|
372
372
|
* Runs the given function and catches any tracable_exceptions. Upon catching such an exception,
|
@@ -121,6 +121,15 @@ replaceString(const string &str, const string &toFind, const string &replaceWith
|
|
121
121
|
}
|
122
122
|
}
|
123
123
|
|
124
|
+
string
|
125
|
+
replaceAll(const string &str, const string &toFind, const string &replaceWith) {
|
126
|
+
string result = str;
|
127
|
+
while (result.find(toFind) != string::npos) {
|
128
|
+
result = replaceString(result, toFind, replaceWith);
|
129
|
+
}
|
130
|
+
return result;
|
131
|
+
}
|
132
|
+
|
124
133
|
string
|
125
134
|
strip(const StaticString &str) {
|
126
135
|
const char *data = str.data();
|
@@ -103,6 +103,11 @@ void splitIncludeSep(const StaticString & restrict_ref str,
|
|
103
103
|
*/
|
104
104
|
string replaceString(const string &str, const string &toFind, const string &replaceWith);
|
105
105
|
|
106
|
+
/**
|
107
|
+
* Like replaceString(), but replace all occurrences of `toFind`.
|
108
|
+
*/
|
109
|
+
string replaceAll(const string &str, const string &toFind, const string &replaceWith);
|
110
|
+
|
106
111
|
/**
|
107
112
|
* Strips leading and trailing whitespaces.
|
108
113
|
*/
|
@@ -29,9 +29,12 @@
|
|
29
29
|
#include <oxt/macros.hpp>
|
30
30
|
#include <sys/types.h>
|
31
31
|
#include <map>
|
32
|
+
#include <set>
|
33
|
+
#include <vector>
|
32
34
|
#include <string>
|
33
35
|
#include <Exceptions.h>
|
34
36
|
#include <Utils/StrIntUtils.h>
|
37
|
+
#include <Utils/Base64.h>
|
35
38
|
#include <Utils/MessageIO.h>
|
36
39
|
|
37
40
|
namespace Passenger {
|
@@ -124,19 +127,25 @@ public:
|
|
124
127
|
}
|
125
128
|
unsigned int i = 0;
|
126
129
|
while (i < argc) {
|
127
|
-
|
130
|
+
string name = argv[i];
|
131
|
+
if (startsWith(name, "--")) {
|
132
|
+
name.erase(0, 2);
|
133
|
+
}
|
134
|
+
name = replaceAll(name, "-", "_");
|
135
|
+
|
136
|
+
store[name] = replaceAll(argv[i + 1], "-", "_");
|
128
137
|
i += 2;
|
129
138
|
}
|
130
139
|
}
|
131
140
|
|
132
141
|
/**
|
133
|
-
* Populates a VariantMap from the data in
|
142
|
+
* Populates a VariantMap from the data in `fd`. MessageIO
|
134
143
|
* is used to read from the file descriptor.
|
135
144
|
*
|
136
145
|
* @throws SystemException
|
137
146
|
* @throws IOException
|
138
147
|
*/
|
139
|
-
void readFrom(int fd) {
|
148
|
+
void readFrom(int fd, const StaticString &messageName = "VariantMap") {
|
140
149
|
TRACE_POINT();
|
141
150
|
vector<string> args;
|
142
151
|
|
@@ -146,7 +155,7 @@ public:
|
|
146
155
|
if (args.size() == 0) {
|
147
156
|
throw IOException("Unexpected empty message received from channel");
|
148
157
|
}
|
149
|
-
if (args[0] !=
|
158
|
+
if (args[0] != messageName) {
|
150
159
|
throw IOException("Unexpected message '" + args[0] + "' received from channel");
|
151
160
|
}
|
152
161
|
if (args.size() % 2 != 1) {
|
@@ -165,19 +174,26 @@ public:
|
|
165
174
|
}
|
166
175
|
|
167
176
|
VariantMap &set(const string &name, const string &value) {
|
168
|
-
|
177
|
+
if (value.empty()) {
|
178
|
+
map<string, string>::iterator it = store.find(name);
|
179
|
+
if (it != store.end()) {
|
180
|
+
store.erase(it);
|
181
|
+
}
|
182
|
+
} else {
|
183
|
+
store[name] = value;
|
184
|
+
}
|
169
185
|
return *this;
|
170
186
|
}
|
171
187
|
|
172
188
|
VariantMap &setDefault(const string &name, const string &value) {
|
173
189
|
if (store.find(name) == store.end()) {
|
174
|
-
|
190
|
+
set(name, value);
|
175
191
|
}
|
176
192
|
return *this;
|
177
193
|
}
|
178
194
|
|
179
195
|
VariantMap &setInt(const string &name, int value) {
|
180
|
-
|
196
|
+
set(name, toString(value));
|
181
197
|
return *this;
|
182
198
|
}
|
183
199
|
|
@@ -189,7 +205,7 @@ public:
|
|
189
205
|
}
|
190
206
|
|
191
207
|
VariantMap &setULL(const string &name, unsigned long long value) {
|
192
|
-
|
208
|
+
set(name, toString(value));
|
193
209
|
return *this;
|
194
210
|
}
|
195
211
|
|
@@ -201,7 +217,7 @@ public:
|
|
201
217
|
}
|
202
218
|
|
203
219
|
VariantMap &setPid(const string &name, pid_t value) {
|
204
|
-
|
220
|
+
set(name, toString((unsigned long long) value));
|
205
221
|
return *this;
|
206
222
|
}
|
207
223
|
|
@@ -213,7 +229,7 @@ public:
|
|
213
229
|
}
|
214
230
|
|
215
231
|
VariantMap &setUid(const string &name, uid_t value) {
|
216
|
-
|
232
|
+
set(name, toString((long long) value));
|
217
233
|
return *this;
|
218
234
|
}
|
219
235
|
|
@@ -225,7 +241,7 @@ public:
|
|
225
241
|
}
|
226
242
|
|
227
243
|
VariantMap &setGid(const string &name, gid_t value) {
|
228
|
-
|
244
|
+
set(name, toString((long long) value));
|
229
245
|
return *this;
|
230
246
|
}
|
231
247
|
|
@@ -237,7 +253,7 @@ public:
|
|
237
253
|
}
|
238
254
|
|
239
255
|
VariantMap &setBool(const string &name, bool value) {
|
240
|
-
|
256
|
+
set(name, value ? "true" : "false");
|
241
257
|
return *this;
|
242
258
|
}
|
243
259
|
|
@@ -248,6 +264,18 @@ public:
|
|
248
264
|
return *this;
|
249
265
|
}
|
250
266
|
|
267
|
+
VariantMap &setStrSet(const string &name, const std::set<string> &value) {
|
268
|
+
std::set<string>::const_iterator it;
|
269
|
+
string result;
|
270
|
+
|
271
|
+
for (it = value.begin(); it != value.end(); it++) {
|
272
|
+
result.append(*it);
|
273
|
+
result.append(1, '\0');
|
274
|
+
}
|
275
|
+
set(name, Base64::encode(result));
|
276
|
+
return *this;
|
277
|
+
}
|
278
|
+
|
251
279
|
const string &get(const string &name, bool required = true) const {
|
252
280
|
map<string, string>::const_iterator it = store.find(name);
|
253
281
|
if (it == store.end()) {
|
@@ -329,6 +357,18 @@ public:
|
|
329
357
|
}
|
330
358
|
return result;
|
331
359
|
}
|
360
|
+
|
361
|
+
vector<string> getStrSet(const string &name, bool required = true,
|
362
|
+
const vector<string> &defaultValue = vector<string>()) const
|
363
|
+
{
|
364
|
+
vector<string> result = defaultValue;
|
365
|
+
const string *str;
|
366
|
+
if (lookup(name, required, &str)) {
|
367
|
+
result.clear();
|
368
|
+
split(Base64::decode(*str), '\0', result);
|
369
|
+
}
|
370
|
+
return result;
|
371
|
+
}
|
332
372
|
|
333
373
|
bool erase(const string &name) {
|
334
374
|
return store.erase(name) != 0;
|
@@ -343,6 +383,15 @@ public:
|
|
343
383
|
unsigned int size() const {
|
344
384
|
return store.size();
|
345
385
|
}
|
386
|
+
|
387
|
+
void addTo(VariantMap &other) const {
|
388
|
+
map<string, string>::const_iterator it;
|
389
|
+
map<string, string>::const_iterator end = store.end();
|
390
|
+
|
391
|
+
for (it = store.begin(); it != end; it++) {
|
392
|
+
other.set(it->first, it->second);
|
393
|
+
}
|
394
|
+
}
|
346
395
|
|
347
396
|
/**
|
348
397
|
* Writes a representation of the contents in this VariantMap to
|
@@ -351,13 +400,13 @@ public:
|
|
351
400
|
*
|
352
401
|
* @throws SystemException
|
353
402
|
*/
|
354
|
-
void writeToFd(int fd) const {
|
403
|
+
void writeToFd(int fd, const StaticString &messageName = "VariantMap") const {
|
355
404
|
map<string, string>::const_iterator it;
|
356
405
|
map<string, string>::const_iterator end = store.end();
|
357
406
|
vector<string> args;
|
358
407
|
|
359
408
|
args.reserve(1 + 2 * store.size());
|
360
|
-
args.push_back(
|
409
|
+
args.push_back(messageName);
|
361
410
|
for (it = store.begin(); it != end; it++) {
|
362
411
|
args.push_back(it->first);
|
363
412
|
args.push_back(it->second);
|