passenger 4.0.48 → 4.0.49
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/.editorconfig +36 -2
- data/.travis.yml +1 -1
- data/CHANGELOG +16 -0
- data/Rakefile +0 -1
- data/build/apache2.rb +4 -4
- data/build/common_library.rb +18 -18
- data/build/cplusplus_support.rb +2 -2
- data/build/documentation.rb +1 -1
- data/build/integration_tests.rb +12 -4
- data/build/misc.rb +12 -7
- data/build/packaging.rb +14 -14
- data/build/preprocessor.rb +10 -10
- data/build/rake_extensions.rb +11 -11
- data/build/ruby_extension.rb +2 -2
- data/dev/ci/inituidgid +24 -0
- data/dev/ci/run_jenkins.sh +57 -0
- data/dev/ci/run_rpm_tests.sh +77 -0
- data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/environment_variables.txt +0 -2
- data/doc/users_guide_snippets/tips.txt +20 -1
- data/ext/apache2/Bucket.cpp +18 -18
- data/ext/apache2/Bucket.h +4 -4
- data/ext/apache2/Configuration.cpp +7 -7
- data/ext/apache2/Configuration.hpp +43 -43
- data/ext/apache2/DirectoryMapper.h +5 -5
- data/ext/apache2/Hooks.cpp +142 -142
- data/ext/apache2/MergeDirConfig.cpp +40 -40
- data/ext/common/Account.h +17 -17
- data/ext/common/AccountsDatabase.h +9 -9
- data/ext/common/AgentsStarter.cpp +2 -2
- data/ext/common/AgentsStarter.h +40 -40
- data/ext/common/ApplicationPool2/Common.h +10 -6
- data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
- data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
- data/ext/common/ApplicationPool2/Group.h +54 -38
- data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
- data/ext/common/ApplicationPool2/Options.h +98 -91
- data/ext/common/ApplicationPool2/Pool.h +70 -69
- data/ext/common/ApplicationPool2/Process.h +21 -21
- data/ext/common/ApplicationPool2/Session.h +11 -11
- data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
- data/ext/common/ApplicationPool2/Socket.h +19 -19
- data/ext/common/ApplicationPool2/Spawner.h +64 -72
- data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
- data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
- data/ext/common/BackgroundEventLoop.cpp +1 -1
- data/ext/common/BackgroundEventLoop.h +2 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/EventedBufferedInput.h +5 -5
- data/ext/common/EventedClient.h +51 -51
- data/ext/common/EventedMessageServer.h +39 -39
- data/ext/common/EventedServer.h +32 -32
- data/ext/common/Exceptions.h +23 -23
- data/ext/common/FileDescriptor.h +18 -18
- data/ext/common/Logging.cpp +1 -1
- data/ext/common/MessageClient.h +27 -27
- data/ext/common/MessageReadersWriters.h +79 -79
- data/ext/common/MessageServer.h +59 -59
- data/ext/common/RandomGenerator.h +12 -12
- data/ext/common/ResourceLocator.h +8 -8
- data/ext/common/SafeLibev.h +54 -25
- data/ext/common/ServerInstanceDir.h +31 -31
- data/ext/common/StaticString.h +50 -48
- data/ext/common/Utils.cpp +73 -78
- data/ext/common/Utils.h +6 -6
- data/ext/common/Utils/Base64.cpp +3 -3
- data/ext/common/Utils/Base64.h +7 -7
- data/ext/common/Utils/BlockingQueue.h +9 -9
- data/ext/common/Utils/BufferedIO.h +17 -17
- data/ext/common/Utils/CachedFileStat.hpp +16 -16
- data/ext/common/Utils/Dechunker.h +25 -25
- data/ext/common/Utils/FileChangeChecker.h +10 -10
- data/ext/common/Utils/MemZeroGuard.h +5 -5
- data/ext/common/Utils/MemoryBarrier.h +1 -1
- data/ext/common/Utils/MessageIO.h +61 -61
- data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
- data/ext/common/Utils/ScopeGuard.h +7 -7
- data/ext/common/Utils/SpeedMeter.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +13 -13
- data/ext/common/Utils/StrIntUtils.h +3 -3
- data/ext/common/Utils/StringScanning.h +5 -5
- data/ext/common/Utils/SystemMetricsCollector.h +2 -2
- data/ext/common/Utils/SystemTime.h +10 -10
- data/ext/common/Utils/Template.h +2 -2
- data/ext/common/Utils/Timer.h +6 -6
- data/ext/common/Utils/VariantMap.h +29 -29
- data/ext/common/agents/Base.cpp +19 -19
- data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
- data/ext/common/agents/HelperAgent/Main.cpp +44 -43
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
- data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
- data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
- data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
- data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
- data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
- data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
- data/ext/common/agents/SpawnPreparer.cpp +4 -4
- data/ext/common/agents/TempDirToucher.c +2 -2
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
- data/ext/common/agents/Watchdog/Main.cpp +22 -22
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
- data/ext/libeio/eio.c +1 -1
- data/ext/nginx/Configuration.c +30 -30
- data/ext/nginx/Configuration.h +1 -1
- data/ext/nginx/ContentHandler.c +54 -54
- data/ext/nginx/ContentHandler.h +3 -3
- data/ext/nginx/StaticContentHandler.c +2 -2
- data/ext/nginx/ngx_http_passenger_module.c +21 -21
- data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
- data/ext/oxt/detail/context.hpp +1 -1
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
- data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
- data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
- data/ext/oxt/dynamic_thread_group.hpp +18 -18
- data/ext/oxt/implementation.cpp +9 -8
- data/ext/oxt/macros.hpp +2 -2
- data/ext/oxt/system_calls.cpp +11 -11
- data/ext/oxt/system_calls.hpp +13 -13
- data/ext/oxt/thread.hpp +22 -14
- data/ext/ruby/passenger_native_support.c +55 -55
- data/lib/phusion_passenger.rb +24 -24
- data/lib/phusion_passenger/common_library.rb +2 -0
- data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
- data/lib/phusion_passenger/packaging.rb +9 -4
- data/lib/phusion_passenger/platform_info/apache.rb +45 -31
- data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
- data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
- data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
- data/lib/phusion_passenger/standalone/command.rb +22 -22
- data/packaging/rpm/LICENSE.txt +19 -0
- data/packaging/rpm/Makefile +13 -0
- data/packaging/rpm/README.md +41 -0
- data/packaging/rpm/Vagrantfile +38 -0
- data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
- data/packaging/rpm/build +170 -0
- data/packaging/rpm/create_project +41 -0
- data/packaging/rpm/git_update +88 -0
- data/packaging/rpm/image/Dockerfile +37 -0
- data/packaging/rpm/image/Gemfile +3 -0
- data/packaging/rpm/image/Gemfile.lock +12 -0
- data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
- data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
- data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
- data/packaging/rpm/image/site-defaults.cfg +168 -0
- data/packaging/rpm/internal/build_tasks.rb +238 -0
- data/packaging/rpm/internal/dummygpg +11 -0
- data/packaging/rpm/internal/exec_build +42 -0
- data/packaging/rpm/internal/get_distro_arch +14 -0
- data/packaging/rpm/internal/get_distro_id +10 -0
- data/packaging/rpm/internal/git_update +27 -0
- data/packaging/rpm/internal/inituidgid +17 -0
- data/packaging/rpm/internal/my_init +344 -0
- data/packaging/rpm/internal/python27 +3 -0
- data/packaging/rpm/internal/repo_update +46 -0
- data/packaging/rpm/internal/setuser +26 -0
- data/packaging/rpm/internal/tracking_helper +40 -0
- data/packaging/rpm/jenkins_release +99 -0
- data/packaging/rpm/lib/build_tasks_support.rb +402 -0
- data/packaging/rpm/lib/preprocessor.rb +341 -0
- data/packaging/rpm/nginx_spec/404.html +119 -0
- data/packaging/rpm/nginx_spec/50x.html +119 -0
- data/packaging/rpm/nginx_spec/index.html +116 -0
- data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
- data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
- data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
- data/packaging/rpm/nginx_spec/nginx.conf +131 -0
- data/packaging/rpm/nginx_spec/nginx.init +144 -0
- data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
- data/packaging/rpm/nginx_spec/nginx.service +15 -0
- data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
- data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
- data/packaging/rpm/nginx_spec/passenger.conf +9 -0
- data/packaging/rpm/nginx_spec/poweredby.png +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
- data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
- data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
- data/packaging/rpm/repo_update +114 -0
- data/packaging/rpm/setup-system +60 -0
- data/packaging/rpm/shell +10 -0
- data/resources/templates/standalone/config.erb +3 -1
- data/test/config.json.rpm-automation +1 -1
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
- data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
- data/test/cxx/ScgiRequestParserTest.cpp +75 -61
- data/test/cxx/UtilsTest.cpp +86 -85
- data/test/gdbinit.example +3 -0
- data/test/integration_tests/nginx_tests.rb +3 -3
- data/test/integration_tests/source_packaging_test.rb +3 -1
- data/test/stub/nginx/nginx.conf.erb +8 -1
- data/test/support/nginx_controller.rb +7 -7
- metadata +62 -17
- metadata.gz.asc +7 -7
- data/build/rpm.rb +0 -128
- data/dev/rpmtool +0 -21
- data/dev/test_rpm_packaging.sh +0 -28
- data/rpm/get_distro_id.py +0 -4
@@ -41,16 +41,16 @@ class AdminController: public MessageServer::Handler {
|
|
41
41
|
private:
|
42
42
|
struct SpecificContext: public MessageServer::ClientContext {
|
43
43
|
};
|
44
|
-
|
44
|
+
|
45
45
|
typedef MessageServer::CommonClientContext CommonClientContext;
|
46
|
-
|
46
|
+
|
47
47
|
LoggingServerPtr server;
|
48
|
-
|
49
|
-
|
48
|
+
|
49
|
+
|
50
50
|
/*********************************************
|
51
51
|
* Message handler methods
|
52
52
|
*********************************************/
|
53
|
-
|
53
|
+
|
54
54
|
void processStatus(CommonClientContext &commonContext, SpecificContext *specificContext,
|
55
55
|
const vector<string> &args)
|
56
56
|
{
|
@@ -60,16 +60,16 @@ private:
|
|
60
60
|
server->dump(stream);
|
61
61
|
writeScalarMessage(commonContext.fd, stream.str());
|
62
62
|
}
|
63
|
-
|
63
|
+
|
64
64
|
public:
|
65
65
|
AdminController(const LoggingServerPtr &server) {
|
66
66
|
this->server = server;
|
67
67
|
}
|
68
|
-
|
68
|
+
|
69
69
|
virtual MessageServer::ClientContextPtr newClient(CommonClientContext &commonContext) {
|
70
70
|
return boost::make_shared<SpecificContext>();
|
71
71
|
}
|
72
|
-
|
72
|
+
|
73
73
|
virtual bool processMessage(CommonClientContext &commonContext,
|
74
74
|
MessageServer::ClientContextPtr &_specificContext,
|
75
75
|
const vector<string> &args)
|
@@ -42,11 +42,11 @@ private:
|
|
42
42
|
unsigned short groupNameSize;
|
43
43
|
unsigned short nodeNameSize;
|
44
44
|
unsigned short categorySize;
|
45
|
-
|
45
|
+
|
46
46
|
size_t totalSize() const {
|
47
47
|
return groupNameSize + nodeNameSize + categorySize + 3;
|
48
48
|
}
|
49
|
-
|
49
|
+
|
50
50
|
StaticString toStaticString() const {
|
51
51
|
if (id == NULL) {
|
52
52
|
return StaticString();
|
@@ -54,7 +54,7 @@ private:
|
|
54
54
|
return StaticString(id, totalSize());
|
55
55
|
}
|
56
56
|
}
|
57
|
-
|
57
|
+
|
58
58
|
public:
|
59
59
|
DataStoreId(const StaticString &groupName, const StaticString &nodeName,
|
60
60
|
const StaticString &category)
|
@@ -62,35 +62,35 @@ public:
|
|
62
62
|
assert(groupName.size() <= USHRT_MAX);
|
63
63
|
assert(nodeName.size() <= USHRT_MAX);
|
64
64
|
assert(category.size() <= USHRT_MAX);
|
65
|
-
|
65
|
+
|
66
66
|
char *end;
|
67
|
-
|
67
|
+
|
68
68
|
id = new char[groupName.size() + nodeName.size() +
|
69
69
|
category.size() + 3];
|
70
70
|
end = id;
|
71
|
-
|
71
|
+
|
72
72
|
memcpy(end, groupName.c_str(), groupName.size());
|
73
73
|
groupNameSize = groupName.size();
|
74
74
|
end += groupName.size();
|
75
75
|
*end = '\0';
|
76
76
|
end++;
|
77
|
-
|
77
|
+
|
78
78
|
memcpy(end, nodeName.c_str(), nodeName.size());
|
79
79
|
nodeNameSize = nodeName.size();
|
80
80
|
end += nodeName.size();
|
81
81
|
*end = '\0';
|
82
82
|
end++;
|
83
|
-
|
83
|
+
|
84
84
|
memcpy(end, category.c_str(), category.size());
|
85
85
|
categorySize = category.size();
|
86
86
|
end += category.size();
|
87
87
|
*end = '\0';
|
88
88
|
}
|
89
|
-
|
89
|
+
|
90
90
|
DataStoreId() {
|
91
91
|
id = NULL;
|
92
92
|
}
|
93
|
-
|
93
|
+
|
94
94
|
DataStoreId(const DataStoreId &other) {
|
95
95
|
if (other.id == NULL) {
|
96
96
|
id = NULL;
|
@@ -102,11 +102,11 @@ public:
|
|
102
102
|
categorySize = other.categorySize;
|
103
103
|
}
|
104
104
|
}
|
105
|
-
|
105
|
+
|
106
106
|
~DataStoreId() {
|
107
107
|
delete id;
|
108
108
|
}
|
109
|
-
|
109
|
+
|
110
110
|
DataStoreId &operator=(const DataStoreId &other) {
|
111
111
|
if (other.id == NULL) {
|
112
112
|
delete id;
|
@@ -127,11 +127,11 @@ public:
|
|
127
127
|
return *this;
|
128
128
|
}
|
129
129
|
}
|
130
|
-
|
130
|
+
|
131
131
|
bool operator<(const DataStoreId &other) const {
|
132
132
|
return toStaticString() < other.toStaticString();
|
133
133
|
}
|
134
|
-
|
134
|
+
|
135
135
|
bool operator==(const DataStoreId &other) const {
|
136
136
|
if (id == NULL) {
|
137
137
|
return other.id == NULL;
|
@@ -143,7 +143,7 @@ public:
|
|
143
143
|
}
|
144
144
|
}
|
145
145
|
}
|
146
|
-
|
146
|
+
|
147
147
|
StaticString getGroupName() const {
|
148
148
|
if (id != NULL) {
|
149
149
|
return StaticString(id, groupNameSize);
|
@@ -151,7 +151,7 @@ public:
|
|
151
151
|
return StaticString();
|
152
152
|
}
|
153
153
|
}
|
154
|
-
|
154
|
+
|
155
155
|
StaticString getNodeName() const {
|
156
156
|
if (id != NULL) {
|
157
157
|
return StaticString(id + groupNameSize + 1,
|
@@ -160,7 +160,7 @@ public:
|
|
160
160
|
return StaticString();
|
161
161
|
}
|
162
162
|
}
|
163
|
-
|
163
|
+
|
164
164
|
StaticString getCategory() const {
|
165
165
|
if (id != NULL) {
|
166
166
|
return StaticString(id + groupNameSize + 1 + nodeNameSize + 1,
|
@@ -81,23 +81,23 @@ public:
|
|
81
81
|
IDENTIFIER,
|
82
82
|
END_OF_DATA
|
83
83
|
};
|
84
|
-
|
84
|
+
|
85
85
|
enum TokenOptions {
|
86
86
|
NO_OPTIONS = 0,
|
87
87
|
REGEXP_OPTION_CASE_INSENSITIVE = 1
|
88
88
|
};
|
89
|
-
|
89
|
+
|
90
90
|
struct Token {
|
91
91
|
TokenType type;
|
92
92
|
int options;
|
93
93
|
unsigned int pos;
|
94
94
|
unsigned int size;
|
95
95
|
StaticString rawValue;
|
96
|
-
|
96
|
+
|
97
97
|
Token() {
|
98
98
|
type = NONE;
|
99
99
|
}
|
100
|
-
|
100
|
+
|
101
101
|
Token(TokenType _type, unsigned int _pos, unsigned int _size, const StaticString &_rawValue)
|
102
102
|
: type(_type),
|
103
103
|
options(NO_OPTIONS),
|
@@ -105,7 +105,7 @@ public:
|
|
105
105
|
size(_size),
|
106
106
|
rawValue(_rawValue)
|
107
107
|
{ }
|
108
|
-
|
108
|
+
|
109
109
|
string toString() const {
|
110
110
|
return Tokenizer::typeToString(type);
|
111
111
|
}
|
@@ -115,47 +115,47 @@ private:
|
|
115
115
|
StaticString data;
|
116
116
|
bool debug;
|
117
117
|
unsigned int pos;
|
118
|
-
|
118
|
+
|
119
119
|
static bool isWhitespace(char ch) {
|
120
120
|
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
|
121
121
|
}
|
122
|
-
|
122
|
+
|
123
123
|
void skipWhitespaces() {
|
124
124
|
while (pos < data.size() && isWhitespace(data[pos])) {
|
125
125
|
pos++;
|
126
126
|
}
|
127
127
|
}
|
128
|
-
|
128
|
+
|
129
129
|
unsigned int available() const {
|
130
130
|
return data.size() - pos;
|
131
131
|
}
|
132
|
-
|
132
|
+
|
133
133
|
char current() const {
|
134
134
|
return data[pos];
|
135
135
|
}
|
136
|
-
|
136
|
+
|
137
137
|
char next() const {
|
138
138
|
return data[pos + 1];
|
139
139
|
}
|
140
|
-
|
140
|
+
|
141
141
|
static bool isIdentifierChar(char ch) {
|
142
142
|
return (ch >= 'a' && ch <= 'z')
|
143
143
|
|| (ch >= 'A' && ch <= 'Z')
|
144
144
|
|| (ch >= '0' && ch <= '9')
|
145
145
|
|| ch == '_';
|
146
146
|
}
|
147
|
-
|
147
|
+
|
148
148
|
static bool isDigit(char ch) {
|
149
149
|
return ch >= '0' && ch <= '9';
|
150
150
|
}
|
151
|
-
|
151
|
+
|
152
152
|
Token logToken(const Token &token) const {
|
153
153
|
if (debug) {
|
154
154
|
printf("# Token: %s\n", token.toString().c_str());
|
155
155
|
}
|
156
156
|
return token;
|
157
157
|
}
|
158
|
-
|
158
|
+
|
159
159
|
void raiseSyntaxError(const string &message = "") {
|
160
160
|
string msg = "Syntax error at character " + toString(pos + 1);
|
161
161
|
if (!message.empty()) {
|
@@ -164,14 +164,14 @@ private:
|
|
164
164
|
}
|
165
165
|
throw SyntaxError(msg);
|
166
166
|
}
|
167
|
-
|
167
|
+
|
168
168
|
void expectingAtLeast(unsigned int size) {
|
169
169
|
if (available() < size) {
|
170
170
|
raiseSyntaxError("at least " + toString(size) +
|
171
171
|
" more characters expected");
|
172
172
|
}
|
173
173
|
}
|
174
|
-
|
174
|
+
|
175
175
|
void expectingNextChar(char ch) {
|
176
176
|
expectingAtLeast(2);
|
177
177
|
if (next() != ch) {
|
@@ -180,13 +180,13 @@ private:
|
|
180
180
|
"'");
|
181
181
|
}
|
182
182
|
}
|
183
|
-
|
183
|
+
|
184
184
|
Token matchToken(TokenType type, unsigned int size = 0) {
|
185
185
|
unsigned int oldPos = pos;
|
186
186
|
pos += size;
|
187
187
|
return Token(type, oldPos, size, data.substr(oldPos, size));
|
188
188
|
}
|
189
|
-
|
189
|
+
|
190
190
|
Token matchTokensStartingWithNegation() {
|
191
191
|
expectingAtLeast(2);
|
192
192
|
switch (next()) {
|
@@ -199,17 +199,17 @@ private:
|
|
199
199
|
return Token(); // Shut up compiler warning.
|
200
200
|
};
|
201
201
|
}
|
202
|
-
|
202
|
+
|
203
203
|
Token matchAnd() {
|
204
204
|
expectingNextChar('&');
|
205
205
|
return matchToken(AND, 2);
|
206
206
|
}
|
207
|
-
|
207
|
+
|
208
208
|
Token matchOr() {
|
209
209
|
expectingNextChar('|');
|
210
210
|
return matchToken(OR, 2);
|
211
211
|
}
|
212
|
-
|
212
|
+
|
213
213
|
Token matchTokensStartingWithEquals() {
|
214
214
|
expectingAtLeast(2);
|
215
215
|
switch (next()) {
|
@@ -222,7 +222,7 @@ private:
|
|
222
222
|
return Token(); // Shut up compiler warning.
|
223
223
|
}
|
224
224
|
}
|
225
|
-
|
225
|
+
|
226
226
|
Token matchTokensStartingWithGreaterThan() {
|
227
227
|
if (available() == 0 || next() != '=') {
|
228
228
|
return matchToken(GREATER_THAN, 1);
|
@@ -230,7 +230,7 @@ private:
|
|
230
230
|
return matchToken(GREATER_THAN_OR_EQUALS, 2);
|
231
231
|
}
|
232
232
|
}
|
233
|
-
|
233
|
+
|
234
234
|
Token matchTokensStartingWithLessThan() {
|
235
235
|
if (available() == 0 || next() != '=') {
|
236
236
|
return matchToken(LESS_THAN, 1);
|
@@ -238,14 +238,14 @@ private:
|
|
238
238
|
return matchToken(LESS_THAN_OR_EQUALS, 2);
|
239
239
|
}
|
240
240
|
}
|
241
|
-
|
241
|
+
|
242
242
|
Token matchRegexp(char terminator) {
|
243
243
|
unsigned int start = pos;
|
244
244
|
bool endFound = false;
|
245
|
-
|
245
|
+
|
246
246
|
// Match initial quote slash.
|
247
247
|
pos++;
|
248
|
-
|
248
|
+
|
249
249
|
// Match rest of regexp including terminating slash.
|
250
250
|
while (pos < data.size() && !endFound) {
|
251
251
|
char ch = current();
|
@@ -263,10 +263,10 @@ private:
|
|
263
263
|
pos++;
|
264
264
|
}
|
265
265
|
}
|
266
|
-
|
266
|
+
|
267
267
|
if (endFound) {
|
268
268
|
Token t(REGEXP, start, pos - start, data.substr(start, pos - start));
|
269
|
-
|
269
|
+
|
270
270
|
// Match regexp options.
|
271
271
|
endFound = false;
|
272
272
|
while (pos < data.size() && !endFound) {
|
@@ -278,21 +278,21 @@ private:
|
|
278
278
|
}
|
279
279
|
pos++;
|
280
280
|
}
|
281
|
-
|
281
|
+
|
282
282
|
return t;
|
283
283
|
} else {
|
284
284
|
raiseSyntaxError("unterminated regular expression");
|
285
285
|
return Token(); // Shut up compiler warning.
|
286
286
|
}
|
287
287
|
}
|
288
|
-
|
288
|
+
|
289
289
|
Token matchString(char terminator) {
|
290
290
|
unsigned int start = pos;
|
291
291
|
bool endFound = false;
|
292
|
-
|
292
|
+
|
293
293
|
// Match initial quote character.
|
294
294
|
pos++;
|
295
|
-
|
295
|
+
|
296
296
|
// Match rest of string including terminating quote.
|
297
297
|
while (pos < data.size() && !endFound) {
|
298
298
|
char ch = current();
|
@@ -310,7 +310,7 @@ private:
|
|
310
310
|
pos++;
|
311
311
|
}
|
312
312
|
}
|
313
|
-
|
313
|
+
|
314
314
|
if (endFound) {
|
315
315
|
return Token(STRING, start, pos - start, data.substr(start, pos - start));
|
316
316
|
} else {
|
@@ -318,20 +318,20 @@ private:
|
|
318
318
|
return Token(); // Shut up compiler warning.
|
319
319
|
}
|
320
320
|
}
|
321
|
-
|
321
|
+
|
322
322
|
Token matchInteger() {
|
323
323
|
unsigned int start = pos;
|
324
|
-
|
324
|
+
|
325
325
|
// Accept initial minus or digit.
|
326
326
|
pos++;
|
327
|
-
|
327
|
+
|
328
328
|
while (pos < data.size() && isDigit(data[pos])) {
|
329
329
|
pos++;
|
330
330
|
}
|
331
|
-
|
331
|
+
|
332
332
|
return Token(INTEGER, start, pos - start, data.substr(start, pos - start));
|
333
333
|
}
|
334
|
-
|
334
|
+
|
335
335
|
Token matchIdentifier() {
|
336
336
|
char ch = current();
|
337
337
|
if ((ch >= 'a' && ch <= 'z') ||
|
@@ -342,7 +342,7 @@ private:
|
|
342
342
|
while (pos < data.size() && isIdentifierChar(current())) {
|
343
343
|
pos++;
|
344
344
|
}
|
345
|
-
|
345
|
+
|
346
346
|
StaticString val = data.substr(start, pos - start);
|
347
347
|
if (val == "true") {
|
348
348
|
return Token(TRUE_LIT, start, pos - start, val);
|
@@ -363,13 +363,13 @@ public:
|
|
363
363
|
this->debug = debug;
|
364
364
|
pos = 0;
|
365
365
|
}
|
366
|
-
|
366
|
+
|
367
367
|
Token getNext() {
|
368
368
|
skipWhitespaces();
|
369
369
|
if (pos >= data.size()) {
|
370
370
|
return logToken(Token(END_OF_DATA, data.size(), 0, ""));
|
371
371
|
}
|
372
|
-
|
372
|
+
|
373
373
|
switch (current()) {
|
374
374
|
case '!':
|
375
375
|
return logToken(matchTokensStartingWithNegation());
|
@@ -413,7 +413,7 @@ public:
|
|
413
413
|
}
|
414
414
|
}
|
415
415
|
}
|
416
|
-
|
416
|
+
|
417
417
|
static string typeToString(TokenType type) {
|
418
418
|
switch (type) {
|
419
419
|
case NONE:
|
@@ -487,9 +487,9 @@ public:
|
|
487
487
|
STATUS_CODE,
|
488
488
|
GC_TIME
|
489
489
|
};
|
490
|
-
|
490
|
+
|
491
491
|
virtual ~Context() { }
|
492
|
-
|
492
|
+
|
493
493
|
virtual string getURI() const = 0;
|
494
494
|
virtual string getController() const = 0;
|
495
495
|
virtual int getResponseTime() const = 0;
|
@@ -497,11 +497,11 @@ public:
|
|
497
497
|
virtual int getStatusCode() const = 0;
|
498
498
|
virtual int getGcTime() const = 0;
|
499
499
|
virtual bool hasHint(const string &name) const = 0;
|
500
|
-
|
500
|
+
|
501
501
|
int getResponseTimeWithoutGc() const {
|
502
502
|
return getResponseTime() - getGcTime();
|
503
503
|
}
|
504
|
-
|
504
|
+
|
505
505
|
string queryStringField(FieldIdentifier id) const {
|
506
506
|
switch (id) {
|
507
507
|
case URI:
|
@@ -522,7 +522,7 @@ public:
|
|
522
522
|
return "";
|
523
523
|
}
|
524
524
|
}
|
525
|
-
|
525
|
+
|
526
526
|
int queryIntField(FieldIdentifier id) const {
|
527
527
|
switch (id) {
|
528
528
|
case RESPONSE_TIME:
|
@@ -537,7 +537,7 @@ public:
|
|
537
537
|
return 0;
|
538
538
|
}
|
539
539
|
}
|
540
|
-
|
540
|
+
|
541
541
|
bool queryBoolField(FieldIdentifier id) const {
|
542
542
|
switch (id) {
|
543
543
|
case URI:
|
@@ -558,7 +558,7 @@ public:
|
|
558
558
|
return false;
|
559
559
|
}
|
560
560
|
}
|
561
|
-
|
561
|
+
|
562
562
|
static ValueType getFieldType(FieldIdentifier id) {
|
563
563
|
switch (id) {
|
564
564
|
case URI:
|
@@ -585,37 +585,37 @@ public:
|
|
585
585
|
int statusCode;
|
586
586
|
int gcTime;
|
587
587
|
set<string> hints;
|
588
|
-
|
588
|
+
|
589
589
|
SimpleContext() {
|
590
590
|
responseTime = 0;
|
591
591
|
statusCode = 0;
|
592
592
|
gcTime = 0;
|
593
593
|
}
|
594
|
-
|
594
|
+
|
595
595
|
virtual string getURI() const {
|
596
596
|
return uri;
|
597
597
|
}
|
598
|
-
|
598
|
+
|
599
599
|
virtual string getController() const {
|
600
600
|
return controller;
|
601
601
|
}
|
602
|
-
|
602
|
+
|
603
603
|
virtual int getResponseTime() const {
|
604
604
|
return responseTime;
|
605
605
|
}
|
606
|
-
|
606
|
+
|
607
607
|
virtual string getStatus() const {
|
608
608
|
return status;
|
609
609
|
}
|
610
|
-
|
610
|
+
|
611
611
|
virtual int getStatusCode() const {
|
612
612
|
return statusCode;
|
613
613
|
}
|
614
|
-
|
614
|
+
|
615
615
|
virtual int getGcTime() const {
|
616
616
|
return gcTime;
|
617
617
|
}
|
618
|
-
|
618
|
+
|
619
619
|
virtual bool hasHint(const string &name) const {
|
620
620
|
return hints.find(name) != hints.end();
|
621
621
|
}
|
@@ -625,7 +625,7 @@ class ContextFromLog: public Context {
|
|
625
625
|
private:
|
626
626
|
StaticString logData;
|
627
627
|
mutable SimpleContext *parsedData;
|
628
|
-
|
628
|
+
|
629
629
|
struct ParseState {
|
630
630
|
unsigned long long requestProcessingStart;
|
631
631
|
unsigned long long requestProcessingEnd;
|
@@ -634,7 +634,7 @@ private:
|
|
634
634
|
unsigned long long gcTimeStart;
|
635
635
|
unsigned long long gcTimeEnd;
|
636
636
|
};
|
637
|
-
|
637
|
+
|
638
638
|
static void parseLine(const StaticString &txnId, unsigned long long timestamp,
|
639
639
|
const StaticString &data, SimpleContext &ctx, ParseState &state)
|
640
640
|
{
|
@@ -662,7 +662,7 @@ private:
|
|
662
662
|
StaticString value = data.substr(data.find(':') + 2);
|
663
663
|
state.gcTimeEnd = stringToULL(value);
|
664
664
|
}
|
665
|
-
|
665
|
+
|
666
666
|
if (state.smallestTimestamp == 0 || timestamp < state.smallestTimestamp) {
|
667
667
|
state.smallestTimestamp = timestamp;
|
668
668
|
}
|
@@ -670,14 +670,14 @@ private:
|
|
670
670
|
state.largestTimestamp = timestamp;
|
671
671
|
}
|
672
672
|
}
|
673
|
-
|
673
|
+
|
674
674
|
static void reallyParse(const StaticString &data, SimpleContext &ctx) {
|
675
675
|
const char *current = data.data();
|
676
676
|
const char *end = data.data() + data.size();
|
677
|
-
|
677
|
+
|
678
678
|
ParseState state;
|
679
679
|
memset(&state, 0, sizeof(state));
|
680
|
-
|
680
|
+
|
681
681
|
while (current < end) {
|
682
682
|
current = skipNewlines(current, end);
|
683
683
|
if (current < end) {
|
@@ -688,7 +688,7 @@ private:
|
|
688
688
|
unsigned long long timestamp;
|
689
689
|
unsigned int writeCount;
|
690
690
|
StaticString lineData;
|
691
|
-
|
691
|
+
|
692
692
|
// If we want to do more complicated analysis we should sort
|
693
693
|
// the lines but for the purposes of ContextFromLog
|
694
694
|
// analyzing the data without sorting is good enough.
|
@@ -700,19 +700,19 @@ private:
|
|
700
700
|
current = endOfLine;
|
701
701
|
}
|
702
702
|
}
|
703
|
-
|
703
|
+
|
704
704
|
if (state.requestProcessingEnd != 0) {
|
705
705
|
ctx.responseTime = int(state.requestProcessingEnd -
|
706
706
|
state.requestProcessingStart);
|
707
707
|
} else if (state.smallestTimestamp != 0) {
|
708
708
|
ctx.responseTime = state.largestTimestamp - state.smallestTimestamp;
|
709
709
|
}
|
710
|
-
|
710
|
+
|
711
711
|
if (state.gcTimeEnd != 0) {
|
712
712
|
ctx.gcTime = state.gcTimeEnd - state.gcTimeStart;
|
713
713
|
}
|
714
714
|
}
|
715
|
-
|
715
|
+
|
716
716
|
static bool splitLine(const StaticString &line, StaticString &txnId,
|
717
717
|
unsigned long long ×tamp, unsigned int &writeCount,
|
718
718
|
StaticString &data)
|
@@ -721,17 +721,17 @@ private:
|
|
721
721
|
if (firstDelim == string::npos) {
|
722
722
|
return false;
|
723
723
|
}
|
724
|
-
|
724
|
+
|
725
725
|
size_t secondDelim = line.find(' ', firstDelim + 1);
|
726
726
|
if (secondDelim == string::npos) {
|
727
727
|
return false;
|
728
728
|
}
|
729
|
-
|
729
|
+
|
730
730
|
size_t thirdDelim = line.find(' ', secondDelim + 1);
|
731
731
|
if (thirdDelim == string::npos) {
|
732
732
|
return false;
|
733
733
|
}
|
734
|
-
|
734
|
+
|
735
735
|
txnId = line.substr(0, firstDelim);
|
736
736
|
timestamp = hexatriToULL(line.substr(firstDelim + 1, secondDelim - firstDelim - 1));
|
737
737
|
writeCount = (unsigned int) hexatriToULL(line.substr(secondDelim + 1,
|
@@ -739,7 +739,7 @@ private:
|
|
739
739
|
data = line.substr(thirdDelim + 1);
|
740
740
|
return true;
|
741
741
|
}
|
742
|
-
|
742
|
+
|
743
743
|
static unsigned long long extractEventTimestamp(const StaticString &data) {
|
744
744
|
size_t pos = data.find('(');
|
745
745
|
if (pos == string::npos) {
|
@@ -757,29 +757,29 @@ private:
|
|
757
757
|
}
|
758
758
|
}
|
759
759
|
}
|
760
|
-
|
760
|
+
|
761
761
|
static bool isNewline(char ch) {
|
762
762
|
return ch == '\n' || ch == '\r';
|
763
763
|
}
|
764
|
-
|
764
|
+
|
765
765
|
static bool isDigit(char ch) {
|
766
766
|
return ch >= '0' && ch <= '9';
|
767
767
|
}
|
768
|
-
|
768
|
+
|
769
769
|
static const char *skipNewlines(const char *current, const char *end) {
|
770
770
|
while (current < end && isNewline(*current)) {
|
771
771
|
current++;
|
772
772
|
}
|
773
773
|
return current;
|
774
774
|
}
|
775
|
-
|
775
|
+
|
776
776
|
static const char *findEndOfLine(const char *current, const char *end) {
|
777
777
|
while (current < end && !isNewline(*current)) {
|
778
778
|
current++;
|
779
779
|
}
|
780
780
|
return current;
|
781
781
|
}
|
782
|
-
|
782
|
+
|
783
783
|
SimpleContext *parse() const {
|
784
784
|
if (parsedData == NULL) {
|
785
785
|
auto_ptr<SimpleContext> ctx(new SimpleContext());
|
@@ -788,41 +788,41 @@ private:
|
|
788
788
|
}
|
789
789
|
return parsedData;
|
790
790
|
}
|
791
|
-
|
791
|
+
|
792
792
|
public:
|
793
793
|
ContextFromLog(const StaticString &logData) {
|
794
794
|
this->logData = logData;
|
795
795
|
parsedData = NULL;
|
796
796
|
}
|
797
|
-
|
797
|
+
|
798
798
|
~ContextFromLog() {
|
799
799
|
delete parsedData;
|
800
800
|
}
|
801
|
-
|
801
|
+
|
802
802
|
virtual string getURI() const {
|
803
803
|
return parse()->uri;
|
804
804
|
}
|
805
|
-
|
805
|
+
|
806
806
|
virtual string getController() const {
|
807
807
|
return parse()->getController();
|
808
808
|
}
|
809
|
-
|
809
|
+
|
810
810
|
virtual int getResponseTime() const {
|
811
811
|
return parse()->getResponseTime();
|
812
812
|
}
|
813
|
-
|
813
|
+
|
814
814
|
virtual string getStatus() const {
|
815
815
|
return parse()->getStatus();
|
816
816
|
}
|
817
|
-
|
817
|
+
|
818
818
|
virtual int getStatusCode() const {
|
819
819
|
return parse()->getStatusCode();
|
820
820
|
}
|
821
|
-
|
821
|
+
|
822
822
|
virtual int getGcTime() const {
|
823
823
|
return parse()->getGcTime();
|
824
824
|
}
|
825
|
-
|
825
|
+
|
826
826
|
virtual bool hasHint(const string &name) const {
|
827
827
|
return parse()->hasHint(name);
|
828
828
|
}
|
@@ -833,7 +833,7 @@ class Filter {
|
|
833
833
|
private:
|
834
834
|
typedef Tokenizer::Token Token;
|
835
835
|
typedef Tokenizer::TokenType TokenType;
|
836
|
-
|
836
|
+
|
837
837
|
struct BooleanComponent;
|
838
838
|
struct MultiExpression;
|
839
839
|
struct Comparison;
|
@@ -842,17 +842,17 @@ private:
|
|
842
842
|
typedef boost::shared_ptr<MultiExpression> MultiExpressionPtr;
|
843
843
|
typedef boost::shared_ptr<Comparison> ComparisonPtr;
|
844
844
|
typedef boost::shared_ptr<FunctionCall> FunctionCallPtr;
|
845
|
-
|
845
|
+
|
846
846
|
struct BooleanComponent {
|
847
847
|
virtual ~BooleanComponent() { }
|
848
848
|
virtual bool evaluate(const Context &ctx) = 0;
|
849
849
|
};
|
850
|
-
|
850
|
+
|
851
851
|
enum LogicalOperator {
|
852
852
|
AND,
|
853
853
|
OR
|
854
854
|
};
|
855
|
-
|
855
|
+
|
856
856
|
enum Comparator {
|
857
857
|
MATCHES,
|
858
858
|
NOT_MATCHES,
|
@@ -864,21 +864,21 @@ private:
|
|
864
864
|
LESS_THAN_OR_EQUALS,
|
865
865
|
UNKNOWN_COMPARATOR
|
866
866
|
};
|
867
|
-
|
867
|
+
|
868
868
|
struct MultiExpression: public BooleanComponent {
|
869
869
|
struct Part {
|
870
870
|
LogicalOperator theOperator;
|
871
871
|
BooleanComponentPtr expression;
|
872
872
|
};
|
873
|
-
|
873
|
+
|
874
874
|
BooleanComponentPtr firstExpression;
|
875
875
|
vector<Part> rest;
|
876
|
-
|
876
|
+
|
877
877
|
virtual bool evaluate(const Context &ctx) {
|
878
878
|
bool result = firstExpression->evaluate(ctx);
|
879
879
|
unsigned int i = 0;
|
880
880
|
bool done = i == rest.size();
|
881
|
-
|
881
|
+
|
882
882
|
while (!done) {
|
883
883
|
Part &nextPart = rest[i];
|
884
884
|
if (nextPart.theOperator == AND) {
|
@@ -890,23 +890,23 @@ private:
|
|
890
890
|
i++;
|
891
891
|
done = done || i == rest.size();
|
892
892
|
}
|
893
|
-
|
893
|
+
|
894
894
|
return result;
|
895
895
|
}
|
896
896
|
};
|
897
|
-
|
897
|
+
|
898
898
|
struct Negation: public BooleanComponent {
|
899
899
|
BooleanComponentPtr expr;
|
900
|
-
|
900
|
+
|
901
901
|
Negation(const BooleanComponentPtr &e)
|
902
902
|
: expr(e)
|
903
903
|
{ }
|
904
|
-
|
904
|
+
|
905
905
|
virtual bool evaluate(const Context &ctx) {
|
906
906
|
return !expr->evaluate(ctx);
|
907
907
|
}
|
908
908
|
};
|
909
|
-
|
909
|
+
|
910
910
|
struct Value {
|
911
911
|
enum Source {
|
912
912
|
REGEXP_LITERAL,
|
@@ -915,7 +915,7 @@ private:
|
|
915
915
|
BOOLEAN_LITERAL,
|
916
916
|
CONTEXT_FIELD_IDENTIFIER
|
917
917
|
};
|
918
|
-
|
918
|
+
|
919
919
|
Source source;
|
920
920
|
union {
|
921
921
|
struct {
|
@@ -930,16 +930,16 @@ private:
|
|
930
930
|
bool boolValue;
|
931
931
|
Context::FieldIdentifier contextFieldIdentifier;
|
932
932
|
} u;
|
933
|
-
|
933
|
+
|
934
934
|
Value() {
|
935
935
|
source = INTEGER_LITERAL;
|
936
936
|
u.intValue = 0;
|
937
937
|
}
|
938
|
-
|
938
|
+
|
939
939
|
Value(const Value &other) {
|
940
940
|
initializeFrom(other);
|
941
941
|
}
|
942
|
-
|
942
|
+
|
943
943
|
Value(bool regexp, const StaticString &value, bool caseInsensitive = false) {
|
944
944
|
if (regexp) {
|
945
945
|
source = REGEXP_LITERAL;
|
@@ -961,32 +961,32 @@ private:
|
|
961
961
|
options);
|
962
962
|
}
|
963
963
|
}
|
964
|
-
|
964
|
+
|
965
965
|
Value(int val) {
|
966
966
|
source = INTEGER_LITERAL;
|
967
967
|
u.intValue = val;
|
968
968
|
}
|
969
|
-
|
969
|
+
|
970
970
|
Value(bool val) {
|
971
971
|
source = BOOLEAN_LITERAL;
|
972
972
|
u.boolValue = val;
|
973
973
|
}
|
974
|
-
|
974
|
+
|
975
975
|
Value(Context::FieldIdentifier identifier) {
|
976
976
|
source = CONTEXT_FIELD_IDENTIFIER;
|
977
977
|
u.contextFieldIdentifier = identifier;
|
978
978
|
}
|
979
|
-
|
979
|
+
|
980
980
|
~Value() {
|
981
981
|
freeStorage();
|
982
982
|
}
|
983
|
-
|
983
|
+
|
984
984
|
Value &operator=(const Value &other) {
|
985
985
|
freeStorage();
|
986
986
|
initializeFrom(other);
|
987
987
|
return *this;
|
988
988
|
}
|
989
|
-
|
989
|
+
|
990
990
|
regex_t *getRegexpValue(const Context &ctx) const {
|
991
991
|
if (source == REGEXP_LITERAL) {
|
992
992
|
return &storedRegexp();
|
@@ -994,7 +994,7 @@ private:
|
|
994
994
|
return NULL;
|
995
995
|
}
|
996
996
|
}
|
997
|
-
|
997
|
+
|
998
998
|
string getStringValue(const Context &ctx) const {
|
999
999
|
switch (source) {
|
1000
1000
|
case REGEXP_LITERAL:
|
@@ -1014,7 +1014,7 @@ private:
|
|
1014
1014
|
return "";
|
1015
1015
|
}
|
1016
1016
|
}
|
1017
|
-
|
1017
|
+
|
1018
1018
|
int getIntegerValue(const Context &ctx) const {
|
1019
1019
|
switch (source) {
|
1020
1020
|
case REGEXP_LITERAL:
|
@@ -1031,7 +1031,7 @@ private:
|
|
1031
1031
|
return 0;
|
1032
1032
|
}
|
1033
1033
|
}
|
1034
|
-
|
1034
|
+
|
1035
1035
|
bool getBooleanValue(const Context &ctx) const {
|
1036
1036
|
switch (source) {
|
1037
1037
|
case REGEXP_LITERAL:
|
@@ -1048,7 +1048,7 @@ private:
|
|
1048
1048
|
return 0;
|
1049
1049
|
}
|
1050
1050
|
}
|
1051
|
-
|
1051
|
+
|
1052
1052
|
ValueType getType() const {
|
1053
1053
|
switch (source) {
|
1054
1054
|
case REGEXP_LITERAL:
|
@@ -1065,16 +1065,16 @@ private:
|
|
1065
1065
|
return UNKNOWN_TYPE;
|
1066
1066
|
}
|
1067
1067
|
}
|
1068
|
-
|
1068
|
+
|
1069
1069
|
private:
|
1070
1070
|
const string &storedString() const {
|
1071
1071
|
return *u.stringOrRegexpValue.stringPointer;
|
1072
1072
|
}
|
1073
|
-
|
1073
|
+
|
1074
1074
|
regex_t &storedRegexp() const {
|
1075
1075
|
return (regex_t &) u.stringOrRegexpValue.regexp.regexp;
|
1076
1076
|
}
|
1077
|
-
|
1077
|
+
|
1078
1078
|
void freeStorage() {
|
1079
1079
|
if (source == REGEXP_LITERAL || source == STRING_LITERAL) {
|
1080
1080
|
storedString().~string();
|
@@ -1083,7 +1083,7 @@ private:
|
|
1083
1083
|
}
|
1084
1084
|
}
|
1085
1085
|
}
|
1086
|
-
|
1086
|
+
|
1087
1087
|
void initializeFrom(const Value &other) {
|
1088
1088
|
int options;
|
1089
1089
|
source = other.source;
|
@@ -1116,24 +1116,24 @@ private:
|
|
1116
1116
|
}
|
1117
1117
|
}
|
1118
1118
|
};
|
1119
|
-
|
1119
|
+
|
1120
1120
|
struct SingleValueComponent: public BooleanComponent {
|
1121
1121
|
Value val;
|
1122
|
-
|
1122
|
+
|
1123
1123
|
SingleValueComponent(const Value &v)
|
1124
1124
|
: val(v)
|
1125
1125
|
{ }
|
1126
|
-
|
1126
|
+
|
1127
1127
|
virtual bool evaluate(const Context &ctx) {
|
1128
1128
|
return val.getBooleanValue(ctx);
|
1129
1129
|
}
|
1130
1130
|
};
|
1131
|
-
|
1131
|
+
|
1132
1132
|
struct Comparison: public BooleanComponent {
|
1133
1133
|
Value subject;
|
1134
1134
|
Comparator comparator;
|
1135
1135
|
Value object;
|
1136
|
-
|
1136
|
+
|
1137
1137
|
virtual bool evaluate(const Context &ctx) {
|
1138
1138
|
switch (subject.getType()) {
|
1139
1139
|
case STRING_TYPE:
|
@@ -1147,7 +1147,7 @@ private:
|
|
1147
1147
|
return false;
|
1148
1148
|
}
|
1149
1149
|
}
|
1150
|
-
|
1150
|
+
|
1151
1151
|
private:
|
1152
1152
|
bool compareStringOrRegexp(const string &str, const Context &ctx) {
|
1153
1153
|
switch (comparator) {
|
@@ -1164,7 +1164,7 @@ private:
|
|
1164
1164
|
return false;
|
1165
1165
|
}
|
1166
1166
|
}
|
1167
|
-
|
1167
|
+
|
1168
1168
|
bool compareInteger(int value, const Context &ctx) {
|
1169
1169
|
int value2 = object.getIntegerValue(ctx);
|
1170
1170
|
switch (comparator) {
|
@@ -1185,7 +1185,7 @@ private:
|
|
1185
1185
|
return false;
|
1186
1186
|
}
|
1187
1187
|
}
|
1188
|
-
|
1188
|
+
|
1189
1189
|
bool compareBoolean(bool value, const Context &ctx) {
|
1190
1190
|
bool value2 = object.getBooleanValue(ctx);
|
1191
1191
|
switch (comparator) {
|
@@ -1199,45 +1199,45 @@ private:
|
|
1199
1199
|
}
|
1200
1200
|
}
|
1201
1201
|
};
|
1202
|
-
|
1202
|
+
|
1203
1203
|
struct FunctionCall: public BooleanComponent {
|
1204
1204
|
vector<Value> arguments;
|
1205
|
-
|
1205
|
+
|
1206
1206
|
virtual void checkArguments() const = 0;
|
1207
1207
|
};
|
1208
|
-
|
1208
|
+
|
1209
1209
|
struct StartsWithFunctionCall: public FunctionCall {
|
1210
1210
|
virtual bool evaluate(const Context &ctx) {
|
1211
1211
|
return startsWith(arguments[0].getStringValue(ctx),
|
1212
1212
|
arguments[1].getStringValue(ctx));
|
1213
1213
|
}
|
1214
|
-
|
1214
|
+
|
1215
1215
|
virtual void checkArguments() const {
|
1216
1216
|
if (arguments.size() != 2) {
|
1217
|
-
throw SyntaxError("you passed " + toString(arguments.size()) +
|
1217
|
+
throw SyntaxError("you passed " + toString(arguments.size()) +
|
1218
1218
|
" argument(s) to starts_with(), but it accepts exactly 2 arguments");
|
1219
1219
|
}
|
1220
1220
|
}
|
1221
1221
|
};
|
1222
|
-
|
1222
|
+
|
1223
1223
|
struct HasHintFunctionCall: public FunctionCall {
|
1224
1224
|
virtual bool evaluate(const Context &ctx) {
|
1225
1225
|
return ctx.hasHint(arguments[0].getStringValue(ctx));
|
1226
1226
|
}
|
1227
|
-
|
1227
|
+
|
1228
1228
|
virtual void checkArguments() const {
|
1229
1229
|
if (arguments.size() != 1) {
|
1230
|
-
throw SyntaxError("you passed " + toString(arguments.size()) +
|
1230
|
+
throw SyntaxError("you passed " + toString(arguments.size()) +
|
1231
1231
|
" argument(s) to has_hint(), but it accepts exactly 1 argument");
|
1232
1232
|
}
|
1233
1233
|
}
|
1234
1234
|
};
|
1235
|
-
|
1235
|
+
|
1236
1236
|
Tokenizer tokenizer;
|
1237
1237
|
BooleanComponentPtr root;
|
1238
1238
|
Token lookahead;
|
1239
1239
|
bool debug;
|
1240
|
-
|
1240
|
+
|
1241
1241
|
static bool isLiteralToken(const Token &token) {
|
1242
1242
|
return token.type == Tokenizer::REGEXP
|
1243
1243
|
|| token.type == Tokenizer::STRING
|
@@ -1245,16 +1245,16 @@ private:
|
|
1245
1245
|
|| token.type == Tokenizer::TRUE_LIT
|
1246
1246
|
|| token.type == Tokenizer::FALSE_LIT;
|
1247
1247
|
}
|
1248
|
-
|
1248
|
+
|
1249
1249
|
static bool isValueToken(const Token &token) {
|
1250
1250
|
return isLiteralToken(token) || token.type == Tokenizer::IDENTIFIER;
|
1251
1251
|
}
|
1252
|
-
|
1252
|
+
|
1253
1253
|
static bool isLogicalOperatorToken(const Token &token) {
|
1254
1254
|
return token.type == Tokenizer::AND
|
1255
1255
|
|| token.type == Tokenizer::OR;
|
1256
1256
|
}
|
1257
|
-
|
1257
|
+
|
1258
1258
|
static Comparator determineComparator(Tokenizer::TokenType type) {
|
1259
1259
|
switch (type) {
|
1260
1260
|
case Tokenizer::MATCHES:
|
@@ -1277,7 +1277,7 @@ private:
|
|
1277
1277
|
return UNKNOWN_COMPARATOR;
|
1278
1278
|
}
|
1279
1279
|
}
|
1280
|
-
|
1280
|
+
|
1281
1281
|
static bool comparatorAcceptsValueTypes(Comparator cmp, ValueType subjectType, ValueType objectType) {
|
1282
1282
|
switch (cmp) {
|
1283
1283
|
case MATCHES:
|
@@ -1297,11 +1297,11 @@ private:
|
|
1297
1297
|
return false; // Shut up compiler warning.
|
1298
1298
|
}
|
1299
1299
|
}
|
1300
|
-
|
1300
|
+
|
1301
1301
|
static string unescapeCString(const StaticString &data) {
|
1302
1302
|
string result;
|
1303
1303
|
result.reserve(data.size());
|
1304
|
-
|
1304
|
+
|
1305
1305
|
const char *current = data.data();
|
1306
1306
|
const char *end = data.data() + data.size();
|
1307
1307
|
while (current < end) {
|
@@ -1331,10 +1331,10 @@ private:
|
|
1331
1331
|
current++;
|
1332
1332
|
}
|
1333
1333
|
}
|
1334
|
-
|
1334
|
+
|
1335
1335
|
return result;
|
1336
1336
|
}
|
1337
|
-
|
1337
|
+
|
1338
1338
|
void logMatch(int level, const char *name) const {
|
1339
1339
|
if (level > 100) {
|
1340
1340
|
// If level is too deep then it's probably a bug.
|
@@ -1347,15 +1347,15 @@ private:
|
|
1347
1347
|
printf("Matching: %s\n", name);
|
1348
1348
|
}
|
1349
1349
|
}
|
1350
|
-
|
1350
|
+
|
1351
1351
|
Token peek() const {
|
1352
1352
|
return lookahead;
|
1353
1353
|
}
|
1354
|
-
|
1354
|
+
|
1355
1355
|
bool peek(Tokenizer::TokenType type) const {
|
1356
1356
|
return lookahead.type == type;
|
1357
1357
|
}
|
1358
|
-
|
1358
|
+
|
1359
1359
|
Token match(TokenType type) {
|
1360
1360
|
if (lookahead.type == type) {
|
1361
1361
|
return match();
|
@@ -1366,13 +1366,13 @@ private:
|
|
1366
1366
|
return Token(); // Shut up compiler warning.
|
1367
1367
|
}
|
1368
1368
|
}
|
1369
|
-
|
1369
|
+
|
1370
1370
|
Token match() {
|
1371
1371
|
Token old = lookahead;
|
1372
1372
|
lookahead = tokenizer.getNext();
|
1373
1373
|
return old;
|
1374
1374
|
}
|
1375
|
-
|
1375
|
+
|
1376
1376
|
void raiseSyntaxError(const string &msg = "", const Token &token = Token()) {
|
1377
1377
|
if (token.type != Tokenizer::NONE) {
|
1378
1378
|
string message = "at character " + toString(token.pos + 1);
|
@@ -1385,11 +1385,11 @@ private:
|
|
1385
1385
|
throw SyntaxError(msg);
|
1386
1386
|
}
|
1387
1387
|
}
|
1388
|
-
|
1388
|
+
|
1389
1389
|
BooleanComponentPtr matchMultiExpression(int level) {
|
1390
1390
|
logMatch(level, "matchMultiExpression()");
|
1391
1391
|
MultiExpressionPtr result = boost::make_shared<MultiExpression>();
|
1392
|
-
|
1392
|
+
|
1393
1393
|
result->firstExpression = matchExpression(level + 1);
|
1394
1394
|
while (isLogicalOperatorToken(peek())) {
|
1395
1395
|
MultiExpression::Part part;
|
@@ -1397,19 +1397,19 @@ private:
|
|
1397
1397
|
part.expression = matchExpression(level + 1);
|
1398
1398
|
result->rest.push_back(part);
|
1399
1399
|
}
|
1400
|
-
|
1400
|
+
|
1401
1401
|
return result;
|
1402
1402
|
}
|
1403
|
-
|
1403
|
+
|
1404
1404
|
BooleanComponentPtr matchExpression(int level) {
|
1405
1405
|
logMatch(level, "matchExpression()");
|
1406
1406
|
bool negate = false;
|
1407
|
-
|
1407
|
+
|
1408
1408
|
if (peek(Tokenizer::NOT)) {
|
1409
1409
|
match();
|
1410
1410
|
negate = true;
|
1411
1411
|
}
|
1412
|
-
|
1412
|
+
|
1413
1413
|
Token next = peek();
|
1414
1414
|
if (next.type == Tokenizer::LPARENTHESIS) {
|
1415
1415
|
match();
|
@@ -1424,7 +1424,7 @@ private:
|
|
1424
1424
|
BooleanComponentPtr component;
|
1425
1425
|
Token ¤t = next;
|
1426
1426
|
match();
|
1427
|
-
|
1427
|
+
|
1428
1428
|
if (peek(Tokenizer::LPARENTHESIS)) {
|
1429
1429
|
component = matchFunctionCall(level + 1, current);
|
1430
1430
|
} else if (determineComparator(peek().type) != UNKNOWN_COMPARATOR) {
|
@@ -1434,7 +1434,7 @@ private:
|
|
1434
1434
|
} else {
|
1435
1435
|
raiseSyntaxError("expected a function call, comparison or boolean literal", current);
|
1436
1436
|
}
|
1437
|
-
|
1437
|
+
|
1438
1438
|
if (negate) {
|
1439
1439
|
return boost::make_shared<Negation>(component);
|
1440
1440
|
} else {
|
@@ -1445,12 +1445,12 @@ private:
|
|
1445
1445
|
return BooleanComponentPtr(); // Shut up compiler warning.
|
1446
1446
|
}
|
1447
1447
|
}
|
1448
|
-
|
1448
|
+
|
1449
1449
|
BooleanComponentPtr matchSingleValueComponent(int level, const Token &token) {
|
1450
1450
|
logMatch(level, "matchSingleValueComponent()");
|
1451
1451
|
return boost::make_shared<SingleValueComponent>(matchLiteral(level + 1, token));
|
1452
1452
|
}
|
1453
|
-
|
1453
|
+
|
1454
1454
|
ComparisonPtr matchComparison(int level, const Token &subjectToken) {
|
1455
1455
|
logMatch(level, "matchComparison()");
|
1456
1456
|
ComparisonPtr comparison = boost::make_shared<Comparison>();
|
@@ -1462,11 +1462,11 @@ private:
|
|
1462
1462
|
}
|
1463
1463
|
return comparison;
|
1464
1464
|
}
|
1465
|
-
|
1465
|
+
|
1466
1466
|
FunctionCallPtr matchFunctionCall(int level, const Token &id) {
|
1467
1467
|
logMatch(level, "matchFunctionCall()");
|
1468
1468
|
FunctionCallPtr function;
|
1469
|
-
|
1469
|
+
|
1470
1470
|
if (id.rawValue == "starts_with") {
|
1471
1471
|
function = boost::make_shared<StartsWithFunctionCall>();
|
1472
1472
|
} else if (id.rawValue == "has_hint") {
|
@@ -1474,7 +1474,7 @@ private:
|
|
1474
1474
|
} else {
|
1475
1475
|
raiseSyntaxError("unknown function '" + id.rawValue + "'", id);
|
1476
1476
|
}
|
1477
|
-
|
1477
|
+
|
1478
1478
|
match(Tokenizer::LPARENTHESIS);
|
1479
1479
|
if (isValueToken(peek())) {
|
1480
1480
|
function->arguments.push_back(matchValue(level + 1, match()));
|
@@ -1487,7 +1487,7 @@ private:
|
|
1487
1487
|
function->checkArguments();
|
1488
1488
|
return function;
|
1489
1489
|
}
|
1490
|
-
|
1490
|
+
|
1491
1491
|
Value matchValue(int level, const Token &token) {
|
1492
1492
|
logMatch(level, "matchValue()");
|
1493
1493
|
if (isLiteralToken(token)) {
|
@@ -1500,7 +1500,7 @@ private:
|
|
1500
1500
|
return Value(); // Shut up compiler warning.
|
1501
1501
|
}
|
1502
1502
|
}
|
1503
|
-
|
1503
|
+
|
1504
1504
|
LogicalOperator matchOperator(int level) {
|
1505
1505
|
logMatch(level, "matchOperator()");
|
1506
1506
|
if (peek(Tokenizer::AND)) {
|
@@ -1516,7 +1516,7 @@ private:
|
|
1516
1516
|
return AND; // Shut up compiler warning.
|
1517
1517
|
}
|
1518
1518
|
}
|
1519
|
-
|
1519
|
+
|
1520
1520
|
Comparator matchComparator(int level) {
|
1521
1521
|
logMatch(level, "matchComparator()");
|
1522
1522
|
Comparator comparator = determineComparator(peek().type);
|
@@ -1529,7 +1529,7 @@ private:
|
|
1529
1529
|
return comparator;
|
1530
1530
|
}
|
1531
1531
|
}
|
1532
|
-
|
1532
|
+
|
1533
1533
|
Value matchLiteral(int level, const Token &token) {
|
1534
1534
|
logMatch(level, "matchLiteral()");
|
1535
1535
|
if (token.type == Tokenizer::REGEXP) {
|
@@ -1553,7 +1553,7 @@ private:
|
|
1553
1553
|
return Value(); // Shut up compiler warning.
|
1554
1554
|
}
|
1555
1555
|
}
|
1556
|
-
|
1556
|
+
|
1557
1557
|
Value matchContextFieldIdentifier(int level, const Token &token) {
|
1558
1558
|
logMatch(level, "matchContextFieldIdentifier()");
|
1559
1559
|
if (token.rawValue == "uri") {
|
@@ -1575,7 +1575,7 @@ private:
|
|
1575
1575
|
return Value(); // Shut up compiler warning.
|
1576
1576
|
}
|
1577
1577
|
}
|
1578
|
-
|
1578
|
+
|
1579
1579
|
public:
|
1580
1580
|
Filter(const StaticString &source, bool debug = false)
|
1581
1581
|
: tokenizer(source, debug)
|
@@ -1586,7 +1586,7 @@ public:
|
|
1586
1586
|
logMatch(0, "end of data");
|
1587
1587
|
match(Tokenizer::END_OF_DATA);
|
1588
1588
|
}
|
1589
|
-
|
1589
|
+
|
1590
1590
|
bool run(const Context &ctx) {
|
1591
1591
|
return root->evaluate(ctx);
|
1592
1592
|
}
|