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.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +36 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG +16 -0
  7. data/Rakefile +0 -1
  8. data/build/apache2.rb +4 -4
  9. data/build/common_library.rb +18 -18
  10. data/build/cplusplus_support.rb +2 -2
  11. data/build/documentation.rb +1 -1
  12. data/build/integration_tests.rb +12 -4
  13. data/build/misc.rb +12 -7
  14. data/build/packaging.rb +14 -14
  15. data/build/preprocessor.rb +10 -10
  16. data/build/rake_extensions.rb +11 -11
  17. data/build/ruby_extension.rb +2 -2
  18. data/dev/ci/inituidgid +24 -0
  19. data/dev/ci/run_jenkins.sh +57 -0
  20. data/dev/ci/run_rpm_tests.sh +77 -0
  21. data/dev/{run_travis.sh → ci/run_travis.sh} +60 -4
  22. data/doc/Users guide Nginx.txt +2 -2
  23. data/doc/users_guide_snippets/environment_variables.txt +0 -2
  24. data/doc/users_guide_snippets/tips.txt +20 -1
  25. data/ext/apache2/Bucket.cpp +18 -18
  26. data/ext/apache2/Bucket.h +4 -4
  27. data/ext/apache2/Configuration.cpp +7 -7
  28. data/ext/apache2/Configuration.hpp +43 -43
  29. data/ext/apache2/DirectoryMapper.h +5 -5
  30. data/ext/apache2/Hooks.cpp +142 -142
  31. data/ext/apache2/MergeDirConfig.cpp +40 -40
  32. data/ext/common/Account.h +17 -17
  33. data/ext/common/AccountsDatabase.h +9 -9
  34. data/ext/common/AgentsStarter.cpp +2 -2
  35. data/ext/common/AgentsStarter.h +40 -40
  36. data/ext/common/ApplicationPool2/Common.h +10 -6
  37. data/ext/common/ApplicationPool2/ComponentInfo.h +2 -2
  38. data/ext/common/ApplicationPool2/DirectSpawner.h +17 -17
  39. data/ext/common/ApplicationPool2/DummySpawner.h +5 -5
  40. data/ext/common/ApplicationPool2/Group.h +54 -38
  41. data/ext/common/ApplicationPool2/Implementation.cpp +76 -49
  42. data/ext/common/ApplicationPool2/Options.h +98 -91
  43. data/ext/common/ApplicationPool2/Pool.h +70 -69
  44. data/ext/common/ApplicationPool2/Process.h +21 -21
  45. data/ext/common/ApplicationPool2/Session.h +11 -11
  46. data/ext/common/ApplicationPool2/SmartSpawner.h +60 -60
  47. data/ext/common/ApplicationPool2/Socket.h +19 -19
  48. data/ext/common/ApplicationPool2/Spawner.h +64 -72
  49. data/ext/common/ApplicationPool2/SpawnerFactory.h +4 -4
  50. data/ext/common/ApplicationPool2/SuperGroup.h +41 -41
  51. data/ext/common/BackgroundEventLoop.cpp +1 -1
  52. data/ext/common/BackgroundEventLoop.h +2 -2
  53. data/ext/common/Constants.h +1 -1
  54. data/ext/common/EventedBufferedInput.h +5 -5
  55. data/ext/common/EventedClient.h +51 -51
  56. data/ext/common/EventedMessageServer.h +39 -39
  57. data/ext/common/EventedServer.h +32 -32
  58. data/ext/common/Exceptions.h +23 -23
  59. data/ext/common/FileDescriptor.h +18 -18
  60. data/ext/common/Logging.cpp +1 -1
  61. data/ext/common/MessageClient.h +27 -27
  62. data/ext/common/MessageReadersWriters.h +79 -79
  63. data/ext/common/MessageServer.h +59 -59
  64. data/ext/common/RandomGenerator.h +12 -12
  65. data/ext/common/ResourceLocator.h +8 -8
  66. data/ext/common/SafeLibev.h +54 -25
  67. data/ext/common/ServerInstanceDir.h +31 -31
  68. data/ext/common/StaticString.h +50 -48
  69. data/ext/common/Utils.cpp +73 -78
  70. data/ext/common/Utils.h +6 -6
  71. data/ext/common/Utils/Base64.cpp +3 -3
  72. data/ext/common/Utils/Base64.h +7 -7
  73. data/ext/common/Utils/BlockingQueue.h +9 -9
  74. data/ext/common/Utils/BufferedIO.h +17 -17
  75. data/ext/common/Utils/CachedFileStat.hpp +16 -16
  76. data/ext/common/Utils/Dechunker.h +25 -25
  77. data/ext/common/Utils/FileChangeChecker.h +10 -10
  78. data/ext/common/Utils/MemZeroGuard.h +5 -5
  79. data/ext/common/Utils/MemoryBarrier.h +1 -1
  80. data/ext/common/Utils/MessageIO.h +61 -61
  81. data/ext/common/Utils/ProcessMetricsCollector.h +40 -40
  82. data/ext/common/Utils/ScopeGuard.h +7 -7
  83. data/ext/common/Utils/SpeedMeter.h +1 -1
  84. data/ext/common/Utils/StrIntUtils.cpp +13 -13
  85. data/ext/common/Utils/StrIntUtils.h +3 -3
  86. data/ext/common/Utils/StringScanning.h +5 -5
  87. data/ext/common/Utils/SystemMetricsCollector.h +2 -2
  88. data/ext/common/Utils/SystemTime.h +10 -10
  89. data/ext/common/Utils/Template.h +2 -2
  90. data/ext/common/Utils/Timer.h +6 -6
  91. data/ext/common/Utils/VariantMap.h +29 -29
  92. data/ext/common/agents/Base.cpp +19 -19
  93. data/ext/common/agents/HelperAgent/AgentOptions.h +1 -1
  94. data/ext/common/agents/HelperAgent/FileBackedPipe.h +6 -6
  95. data/ext/common/agents/HelperAgent/Main.cpp +44 -43
  96. data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
  97. data/ext/common/agents/HelperAgent/RequestHandler.h +29 -28
  98. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +56 -50
  99. data/ext/common/agents/LoggingAgent/AdminController.h +8 -8
  100. data/ext/common/agents/LoggingAgent/DataStoreId.h +17 -17
  101. data/ext/common/agents/LoggingAgent/FilterSupport.h +167 -167
  102. data/ext/common/agents/LoggingAgent/LoggingServer.h +122 -122
  103. data/ext/common/agents/LoggingAgent/Main.cpp +7 -7
  104. data/ext/common/agents/LoggingAgent/RemoteSender.h +54 -54
  105. data/ext/common/agents/SpawnPreparer.cpp +4 -4
  106. data/ext/common/agents/TempDirToucher.c +2 -2
  107. data/ext/common/agents/Watchdog/AgentWatcher.cpp +47 -47
  108. data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +7 -7
  109. data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +7 -7
  110. data/ext/common/agents/Watchdog/Main.cpp +22 -22
  111. data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +9 -9
  112. data/ext/libeio/eio.c +1 -1
  113. data/ext/nginx/Configuration.c +30 -30
  114. data/ext/nginx/Configuration.h +1 -1
  115. data/ext/nginx/ContentHandler.c +54 -54
  116. data/ext/nginx/ContentHandler.h +3 -3
  117. data/ext/nginx/StaticContentHandler.c +2 -2
  118. data/ext/nginx/ngx_http_passenger_module.c +21 -21
  119. data/ext/oxt/detail/backtrace_enabled.hpp +1 -1
  120. data/ext/oxt/detail/context.hpp +1 -1
  121. data/ext/oxt/detail/spin_lock_darwin.hpp +4 -4
  122. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +3 -3
  123. data/ext/oxt/detail/spin_lock_pthreads.hpp +4 -4
  124. data/ext/oxt/detail/tracable_exception_disabled.hpp +1 -1
  125. data/ext/oxt/dynamic_thread_group.hpp +18 -18
  126. data/ext/oxt/implementation.cpp +9 -8
  127. data/ext/oxt/macros.hpp +2 -2
  128. data/ext/oxt/system_calls.cpp +11 -11
  129. data/ext/oxt/system_calls.hpp +13 -13
  130. data/ext/oxt/thread.hpp +22 -14
  131. data/ext/ruby/passenger_native_support.c +55 -55
  132. data/lib/phusion_passenger.rb +24 -24
  133. data/lib/phusion_passenger/common_library.rb +2 -0
  134. data/lib/phusion_passenger/loader_shared_helpers.rb +18 -18
  135. data/lib/phusion_passenger/packaging.rb +9 -4
  136. data/lib/phusion_passenger/platform_info/apache.rb +45 -31
  137. data/lib/phusion_passenger/platform_info/compiler.rb +11 -11
  138. data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
  139. data/lib/phusion_passenger/request_handler/thread_handler.rb +8 -8
  140. data/lib/phusion_passenger/standalone/app_finder.rb +16 -16
  141. data/lib/phusion_passenger/standalone/command.rb +22 -22
  142. data/packaging/rpm/LICENSE.txt +19 -0
  143. data/packaging/rpm/Makefile +13 -0
  144. data/packaging/rpm/README.md +41 -0
  145. data/packaging/rpm/Vagrantfile +38 -0
  146. data/{rpm/Vagrantfile → packaging/rpm/Vagrantfile.centos} +0 -0
  147. data/packaging/rpm/build +170 -0
  148. data/packaging/rpm/create_project +41 -0
  149. data/packaging/rpm/git_update +88 -0
  150. data/packaging/rpm/image/Dockerfile +37 -0
  151. data/packaging/rpm/image/Gemfile +3 -0
  152. data/packaging/rpm/image/Gemfile.lock +12 -0
  153. data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +19 -0
  154. data/packaging/rpm/image/amazon2014-i386.cfg +96 -0
  155. data/packaging/rpm/image/amazon2014-x86_64.cfg +96 -0
  156. data/packaging/rpm/image/site-defaults.cfg +168 -0
  157. data/packaging/rpm/internal/build_tasks.rb +238 -0
  158. data/packaging/rpm/internal/dummygpg +11 -0
  159. data/packaging/rpm/internal/exec_build +42 -0
  160. data/packaging/rpm/internal/get_distro_arch +14 -0
  161. data/packaging/rpm/internal/get_distro_id +10 -0
  162. data/packaging/rpm/internal/git_update +27 -0
  163. data/packaging/rpm/internal/inituidgid +17 -0
  164. data/packaging/rpm/internal/my_init +344 -0
  165. data/packaging/rpm/internal/python27 +3 -0
  166. data/packaging/rpm/internal/repo_update +46 -0
  167. data/packaging/rpm/internal/setuser +26 -0
  168. data/packaging/rpm/internal/tracking_helper +40 -0
  169. data/packaging/rpm/jenkins_release +99 -0
  170. data/packaging/rpm/lib/build_tasks_support.rb +402 -0
  171. data/packaging/rpm/lib/preprocessor.rb +341 -0
  172. data/packaging/rpm/nginx_spec/404.html +119 -0
  173. data/packaging/rpm/nginx_spec/50x.html +119 -0
  174. data/packaging/rpm/nginx_spec/index.html +116 -0
  175. data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +13 -0
  176. data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
  177. data/packaging/rpm/nginx_spec/nginx-upgrade +13 -0
  178. data/packaging/rpm/nginx_spec/nginx-upgrade.8 +151 -0
  179. data/packaging/rpm/nginx_spec/nginx.conf +131 -0
  180. data/packaging/rpm/nginx_spec/nginx.init +144 -0
  181. data/packaging/rpm/nginx_spec/nginx.logrotate +13 -0
  182. data/packaging/rpm/nginx_spec/nginx.service +15 -0
  183. data/packaging/rpm/nginx_spec/nginx.spec.template +559 -0
  184. data/packaging/rpm/nginx_spec/nginx.sysconfig +4 -0
  185. data/packaging/rpm/nginx_spec/passenger.conf +9 -0
  186. data/packaging/rpm/nginx_spec/poweredby.png +0 -0
  187. data/{rpm → packaging/rpm/passenger_spec}/apache-passenger.conf.in +0 -0
  188. data/{rpm → packaging/rpm/passenger_spec}/config.json +0 -0
  189. data/{rpm → packaging/rpm/passenger_spec}/passenger.logrotate +0 -0
  190. data/{rpm → packaging/rpm/passenger_spec}/passenger.spec.template +58 -31
  191. data/{rpm → packaging/rpm/passenger_spec}/passenger_dynamic_thread_group.patch +0 -0
  192. data/{rpm → packaging/rpm/passenger_spec}/passenger_tests_default_config_example.patch +0 -0
  193. data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -0
  194. data/{rpm → packaging/rpm/passenger_spec}/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +0 -0
  195. data/packaging/rpm/repo_update +114 -0
  196. data/packaging/rpm/setup-system +60 -0
  197. data/packaging/rpm/shell +10 -0
  198. data/resources/templates/standalone/config.erb +3 -1
  199. data/test/config.json.rpm-automation +1 -1
  200. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +11 -11
  201. data/test/cxx/ApplicationPool2/OptionsTest.cpp +5 -5
  202. data/test/cxx/ApplicationPool2/PoolTest.cpp +129 -89
  203. data/test/cxx/ApplicationPool2/ProcessTest.cpp +15 -15
  204. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +22 -22
  205. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +11 -11
  206. data/test/cxx/ScgiRequestParserTest.cpp +75 -61
  207. data/test/cxx/UtilsTest.cpp +86 -85
  208. data/test/gdbinit.example +3 -0
  209. data/test/integration_tests/nginx_tests.rb +3 -3
  210. data/test/integration_tests/source_packaging_test.rb +3 -1
  211. data/test/stub/nginx/nginx.conf.erb +8 -1
  212. data/test/support/nginx_controller.rb +7 -7
  213. metadata +62 -17
  214. metadata.gz.asc +7 -7
  215. data/build/rpm.rb +0 -128
  216. data/dev/rpmtool +0 -21
  217. data/dev/test_rpm_packaging.sh +0 -28
  218. data/rpm/get_distro_id.py +0 -4
@@ -72,14 +72,14 @@ class LoggingServer: public EventedMessageServer {
72
72
  private:
73
73
  static const int MAX_LOG_SINK_CACHE_SIZE = 512;
74
74
  static const int GARBAGE_COLLECTION_TIMEOUT = 4500; // 1 hour 15 minutes
75
-
75
+
76
76
  struct LogSink;
77
77
  typedef boost::shared_ptr<LogSink> LogSinkPtr;
78
78
  typedef map<string, LogSinkPtr> LogSinkCache;
79
-
79
+
80
80
  struct LogSink {
81
81
  LoggingServer *server;
82
-
82
+
83
83
  /**
84
84
  * Marks how many times this LogSink is currently opened, i.e. the
85
85
  * number of Transaction objects currently referencing this LogSink.
@@ -87,27 +87,27 @@ private:
87
87
  * (opened == 0) == (this LogSink is in LoggingServer.inactiveLogSinks)
88
88
  */
89
89
  int opened;
90
-
90
+
91
91
  /** Last time this LogSink hit an open count of 0. */
92
92
  ev_tstamp lastUsed;
93
-
93
+
94
94
  /** Last time data was actually written to the underlying storage device. */
95
95
  ev_tstamp lastFlushed;
96
96
 
97
97
  /** The amount of data that has been written to this sink so far. */
98
98
  unsigned int writtenTo;
99
-
99
+
100
100
  /**
101
101
  * This LogSink's iterator inside LoggingServer.logSinkCache.
102
102
  */
103
103
  LogSinkCache::iterator cacheIterator;
104
-
104
+
105
105
  /**
106
106
  * This LogSink's iterator inside LoggingServer.inactiveLogSinks.
107
107
  * Only valid when opened == 0.
108
108
  */
109
109
  list<LogSinkPtr>::iterator inactiveLogSinksIterator;
110
-
110
+
111
111
  LogSink(LoggingServer *_server) {
112
112
  server = _server;
113
113
  opened = 0;
@@ -115,12 +115,12 @@ private:
115
115
  lastFlushed = lastUsed;
116
116
  writtenTo = 0;
117
117
  }
118
-
118
+
119
119
  virtual ~LogSink() {
120
120
  // We really want to flush() here but can't call virtual
121
121
  // functions in destructor. :(
122
122
  }
123
-
123
+
124
124
  virtual bool isRemote() const {
125
125
  return false;
126
126
  }
@@ -129,25 +129,25 @@ private:
129
129
  virtual unsigned int defaultFlushInterval() const {
130
130
  return 5;
131
131
  }
132
-
132
+
133
133
  virtual void append(const DataStoreId &dataStoreId,
134
134
  const StaticString &data)
135
135
  {
136
136
  writtenTo += data.size();
137
137
  }
138
-
138
+
139
139
  virtual bool flush() {
140
140
  lastFlushed = ev_now(server->getLoop());
141
141
  return true;
142
142
  }
143
-
143
+
144
144
  virtual void dump(ostream &stream) const { }
145
145
  };
146
-
146
+
147
147
  struct LogFileSink: public LogSink {
148
148
  string filename;
149
149
  FileDescriptor fd;
150
-
150
+
151
151
  LogFileSink(LoggingServer *server, const string &filename)
152
152
  : LogSink(server)
153
153
  {
@@ -164,11 +164,11 @@ private:
164
164
  throw FileSystemException("Cannnot open file", e, filename);
165
165
  }
166
166
  }
167
-
167
+
168
168
  virtual ~LogFileSink() {
169
169
  flush();
170
170
  }
171
-
171
+
172
172
  virtual void append(const DataStoreId &dataStoreId, const StaticString &data) {
173
173
  LogSink::append(dataStoreId, data);
174
174
  syscalls::write(fd, data.data(), data.size());
@@ -182,9 +182,9 @@ private:
182
182
  stream << " WrittenTo : " << writtenTo << "\n";
183
183
  }
184
184
  };
185
-
185
+
186
186
  typedef boost::shared_ptr<LogFileSink> LogFileSinkPtr;
187
-
187
+
188
188
  struct RemoteSink: public LogSink {
189
189
  /* RemoteSender compresses the data with zlib before sending it
190
190
  * to the server. Even including Base64 and URL encoding overhead,
@@ -202,13 +202,13 @@ private:
202
202
  static const unsigned int BUFFER_CAPACITY =
203
203
  4 * 64 * 1024 -
204
204
  16 * 1024;
205
-
205
+
206
206
  string unionStationKey;
207
207
  string nodeName;
208
208
  string category;
209
209
  char buffer[BUFFER_CAPACITY];
210
210
  unsigned int bufferSize;
211
-
211
+
212
212
  RemoteSink(LoggingServer *server, const string &unionStationKey,
213
213
  const string &nodeName, const string &category)
214
214
  : LogSink(server)
@@ -218,11 +218,11 @@ private:
218
218
  this->category = category;
219
219
  this->bufferSize = 0;
220
220
  }
221
-
221
+
222
222
  virtual ~RemoteSink() {
223
223
  flush();
224
224
  }
225
-
225
+
226
226
  virtual bool isRemote() const {
227
227
  return true;
228
228
  }
@@ -230,14 +230,14 @@ private:
230
230
  virtual unsigned int defaultFlushInterval() const {
231
231
  return 5;
232
232
  }
233
-
233
+
234
234
  virtual void append(const DataStoreId &dataStoreId, const StaticString &data) {
235
235
  LogSink::append(dataStoreId, data);
236
236
  if (bufferSize + data.size() > BUFFER_CAPACITY) {
237
237
  StaticString data2[2];
238
238
  data2[0] = StaticString(buffer, bufferSize);
239
239
  data2[1] = data;
240
-
240
+
241
241
  server->remoteSender.schedule(unionStationKey, nodeName,
242
242
  category, data2, 2);
243
243
  lastFlushed = ev_now(server->getLoop());
@@ -247,7 +247,7 @@ private:
247
247
  bufferSize += data.size();
248
248
  }
249
249
  }
250
-
250
+
251
251
  virtual bool flush() {
252
252
  if (bufferSize > 0) {
253
253
  lastFlushed = ev_now(server->getLoop());
@@ -266,7 +266,7 @@ private:
266
266
  string inspect() const {
267
267
  return "(key=" + unionStationKey + ", node=" + nodeName + ", category=" + category + ")";
268
268
  }
269
-
269
+
270
270
  virtual void dump(ostream &stream) const {
271
271
  stream << " * Remote sink\n";
272
272
  stream << " Key : " << unionStationKey << "\n";
@@ -279,7 +279,7 @@ private:
279
279
  stream << " BufferSize : " << bufferSize << "\n";
280
280
  }
281
281
  };
282
-
282
+
283
283
  struct Transaction {
284
284
  LoggingServer *server;
285
285
  LogSinkPtr logSink;
@@ -291,13 +291,13 @@ private:
291
291
  bool crashProtect, discarded;
292
292
  string data;
293
293
  string filters;
294
-
294
+
295
295
  Transaction(LoggingServer *server, ev_tstamp createdAt) {
296
296
  this->server = server;
297
297
  this->createdAt = createdAt;
298
298
  data.reserve(8 * 1024);
299
299
  }
300
-
300
+
301
301
  ~Transaction() {
302
302
  if (logSink != NULL) {
303
303
  if (!discarded && passesFilter()) {
@@ -306,24 +306,24 @@ private:
306
306
  server->closeLogSink(logSink);
307
307
  }
308
308
  }
309
-
309
+
310
310
  StaticString getGroupName() const {
311
311
  return dataStoreId.getGroupName();
312
312
  }
313
-
313
+
314
314
  StaticString getNodeName() const {
315
315
  return dataStoreId.getNodeName();
316
316
  }
317
-
317
+
318
318
  StaticString getCategory() const {
319
319
  return dataStoreId.getCategory();
320
320
  }
321
-
321
+
322
322
  void discard() {
323
323
  data.clear();
324
324
  discarded = true;
325
325
  }
326
-
326
+
327
327
  void dump(ostream &stream) const {
328
328
  stream << " * Transaction " << txnId << "\n";
329
329
  stream << " Created at: " << distanceOfTimeInWords((time_t) createdAt) << " ago\n";
@@ -332,18 +332,18 @@ private:
332
332
  stream << " Category : " << getCategory() << "\n";
333
333
  stream << " Refcount : " << refcount << "\n";
334
334
  }
335
-
335
+
336
336
  private:
337
337
  bool passesFilter() {
338
338
  if (filters.empty()) {
339
339
  return true;
340
340
  }
341
-
341
+
342
342
  const char *current = filters.data();
343
343
  const char *end = filters.data() + filters.size();
344
344
  bool result = true;
345
345
  FilterSupport::ContextFromLog ctx(data);
346
-
346
+
347
347
  // 'filters' may contain multiple filter sources, separated
348
348
  // by '\1' characters. Process each.
349
349
  while (current < end && result) {
@@ -352,24 +352,24 @@ private:
352
352
  if (pos == string::npos) {
353
353
  pos = tmp.size();
354
354
  }
355
-
355
+
356
356
  StaticString source(current, pos);
357
357
  FilterSupport::Filter &filter = server->compileFilter(source);
358
358
  result = filter.run(ctx);
359
-
359
+
360
360
  current = tmp.data() + pos + 1;
361
361
  }
362
362
  return result;
363
363
  }
364
364
  };
365
-
365
+
366
366
  typedef boost::shared_ptr<Transaction> TransactionPtr;
367
-
367
+
368
368
  enum ClientType {
369
369
  UNINITIALIZED,
370
370
  LOGGER
371
371
  };
372
-
372
+
373
373
  struct Client: public EventedMessageClient {
374
374
  string nodeName;
375
375
  ClientType type;
@@ -382,7 +382,7 @@ private:
382
382
  ScalarMessage dataReader;
383
383
  TransactionPtr currentTransaction;
384
384
  string currentTimestamp;
385
-
385
+
386
386
  Client(struct ev_loop *loop, const FileDescriptor &fd)
387
387
  : EventedMessageClient(loop, fd)
388
388
  {
@@ -406,12 +406,12 @@ private:
406
406
  stream << " Outbox : " << outbox.size() << " bytes\n";
407
407
  }
408
408
  };
409
-
409
+
410
410
  typedef boost::shared_ptr<Client> ClientPtr;
411
411
  typedef map<string, TransactionPtr> TransactionMap;
412
-
412
+
413
413
  typedef boost::shared_ptr<FilterSupport::Filter> FilterPtr;
414
-
414
+
415
415
  RemoteSender remoteSender;
416
416
  ev::timer garbageCollectionTimer;
417
417
  ev::timer sinkFlushingTimer;
@@ -434,12 +434,12 @@ private:
434
434
  unsigned long long exitBeginTime;
435
435
  int sinkFlushInterval;
436
436
  string dumpFile;
437
-
437
+
438
438
  void sendErrorToClient(Client *client, const string &message) {
439
439
  client->writeArrayMessage("error", message.c_str(), NULL);
440
440
  logError(client, message);
441
441
  }
442
-
442
+
443
443
  bool expectingArgumentsCount(Client *client, const vector<StaticString> &args, unsigned int size) {
444
444
  if (args.size() == size) {
445
445
  return true;
@@ -449,7 +449,7 @@ private:
449
449
  return false;
450
450
  }
451
451
  }
452
-
452
+
453
453
  bool expectingMinArgumentsCount(Client *client, const vector<StaticString> &args, unsigned int size) {
454
454
  if (args.size() >= size) {
455
455
  return true;
@@ -459,7 +459,7 @@ private:
459
459
  return false;
460
460
  }
461
461
  }
462
-
462
+
463
463
  bool expectingLoggerType(Client *client) {
464
464
  if (client->type == LOGGER) {
465
465
  return true;
@@ -469,7 +469,7 @@ private:
469
469
  return false;
470
470
  }
471
471
  }
472
-
472
+
473
473
  bool checkWhetherConnectionAreAcceptable(Client *client) {
474
474
  if (refuseNewConnections) {
475
475
  client->writeArrayMessage("server shutting down", NULL);
@@ -479,7 +479,7 @@ private:
479
479
  return true;
480
480
  }
481
481
  }
482
-
482
+
483
483
  static bool getBool(const vector<StaticString> &args, unsigned int index,
484
484
  bool defaultValue = false)
485
485
  {
@@ -489,7 +489,7 @@ private:
489
489
  return defaultValue;
490
490
  }
491
491
  }
492
-
492
+
493
493
  static StaticString getStaticString(const vector<StaticString> &args,
494
494
  unsigned int index, const StaticString &defaultValue = "")
495
495
  {
@@ -499,7 +499,7 @@ private:
499
499
  return defaultValue;
500
500
  }
501
501
  }
502
-
502
+
503
503
  bool validTxnId(const StaticString &txnId) const {
504
504
  // must contain timestamp
505
505
  // must contain separator
@@ -507,13 +507,13 @@ private:
507
507
  // must not be too large
508
508
  return !txnId.empty();
509
509
  }
510
-
510
+
511
511
  bool validUnionStationKey(const StaticString &key) const {
512
512
  // TODO: must be hexadecimal
513
513
  // TODO: must not be too large
514
514
  return !key.empty();
515
515
  }
516
-
516
+
517
517
  bool validLogContent(const StaticString &data) const {
518
518
  const char *current = data.c_str();
519
519
  const char *end = current + data.size();
@@ -526,18 +526,18 @@ private:
526
526
  }
527
527
  return true;
528
528
  }
529
-
529
+
530
530
  bool validTimestamp(const StaticString &timestamp) const {
531
531
  // TODO: must be hexadecimal
532
532
  // TODO: must not be too large
533
533
  return true;
534
534
  }
535
-
535
+
536
536
  bool supportedCategory(const StaticString &category) const {
537
537
  return category == "requests" || category == "processes"
538
538
  || category == "exceptions" || category == "system_metrics";
539
539
  }
540
-
540
+
541
541
  LogSinkPtr openLogFile() {
542
542
  string cacheKey = "file:" + dumpFile;
543
543
  LogSinkPtr result;
@@ -559,7 +559,7 @@ private:
559
559
  }
560
560
  return result;
561
561
  }
562
-
562
+
563
563
  LogSinkPtr openRemoteSink(const StaticString &unionStationKey, const string &nodeName,
564
564
  const string &category)
565
565
  {
@@ -569,7 +569,7 @@ private:
569
569
  cacheKey.append(nodeName);
570
570
  cacheKey.append(1, '\0');
571
571
  cacheKey.append(category);
572
-
572
+
573
573
  LogSinkPtr result;
574
574
  LogSinkCache::iterator it = logSinkCache.find(cacheKey);
575
575
  if (it == logSinkCache.end()) {
@@ -590,7 +590,7 @@ private:
590
590
  }
591
591
  return result;
592
592
  }
593
-
593
+
594
594
  /**
595
595
  * 'Closes' the given log sink. It's not actually deleted from memory;
596
596
  * instead it's marked as inactive and cached for later use. May be
@@ -611,7 +611,7 @@ private:
611
611
  trimLogSinkCache(MAX_LOG_SINK_CACHE_SIZE);
612
612
  }
613
613
  }
614
-
614
+
615
615
  /** Try to reduce the log sink cache size to the given size. */
616
616
  void trimLogSinkCache(unsigned int size) {
617
617
  while (!inactiveLogSinks.empty() && logSinkCache.size() > size) {
@@ -621,7 +621,7 @@ private:
621
621
  logSinkCache.erase(logSink->cacheIterator);
622
622
  }
623
623
  }
624
-
624
+
625
625
  FilterSupport::Filter &compileFilter(const StaticString &source) {
626
626
  // TODO: garbage collect filters based on time
627
627
  FilterPtr filter = filters.get(source);
@@ -631,7 +631,7 @@ private:
631
631
  }
632
632
  return *filter;
633
633
  }
634
-
634
+
635
635
  bool writeLogEntry(Client *client, const TransactionPtr &transaction,
636
636
  const StaticString &timestamp, const StaticString &data)
637
637
  {
@@ -652,7 +652,7 @@ private:
652
652
  }
653
653
  return false;
654
654
  }
655
-
655
+
656
656
  char writeCountStr[sizeof(unsigned int) * 2 + 1];
657
657
  integerToHexatri(transaction->writeCount, writeCountStr);
658
658
  transaction->writeCount++;
@@ -666,7 +666,7 @@ private:
666
666
  transaction->data.append("\n");
667
667
  return true;
668
668
  }
669
-
669
+
670
670
  void writeDetachEntry(Client *client, const TransactionPtr &transaction) {
671
671
  char timestamp[2 * sizeof(unsigned long long) + 1];
672
672
  // Must use System::getUsec() here instead of ev_now() because the
@@ -674,13 +674,13 @@ private:
674
674
  integerToHexatri<unsigned long long>(SystemTime::getUsec(), timestamp);
675
675
  writeDetachEntry(client, transaction, timestamp);
676
676
  }
677
-
677
+
678
678
  void writeDetachEntry(Client *client, const TransactionPtr &transaction,
679
679
  const StaticString &timestamp)
680
680
  {
681
681
  writeLogEntry(client, transaction, timestamp, "DETACH");
682
682
  }
683
-
683
+
684
684
  bool requireRights(Client *client, Account::Rights rights) {
685
685
  if (client->messageServer.account->hasRights(rights)) {
686
686
  return true;
@@ -693,7 +693,7 @@ private:
693
693
  return false;
694
694
  }
695
695
  }
696
-
696
+
697
697
  bool isDirectory(const string &dir, struct dirent *entry) const {
698
698
  #if defined(__sun__) || defined(sun) || defined(_AIX)
699
699
  string path = dir;
@@ -704,7 +704,7 @@ private:
704
704
  return entry->d_type == DT_DIR;
705
705
  #endif
706
706
  }
707
-
707
+
708
708
  bool looksLikeNumber(const char *str) const {
709
709
  const char *current = str;
710
710
  while (*current != '\0') {
@@ -716,13 +716,13 @@ private:
716
716
  }
717
717
  return true;
718
718
  }
719
-
719
+
720
720
  /* Release all inactive log sinks that have been inactive for more than
721
721
  * GARBAGE_COLLECTION_TIMEOUT seconds.
722
722
  */
723
723
  void releaseInactiveLogSinks(ev_tstamp now) {
724
724
  bool done = false;
725
-
725
+
726
726
  while (!done && !inactiveLogSinks.empty()) {
727
727
  const LogSinkPtr logSink = inactiveLogSinks.front();
728
728
  if (now - logSink->lastUsed >= GARBAGE_COLLECTION_TIMEOUT) {
@@ -734,7 +734,7 @@ private:
734
734
  }
735
735
  }
736
736
  }
737
-
737
+
738
738
  void garbageCollect(ev::timer &timer, int revents) {
739
739
  P_DEBUG("Garbage collection time");
740
740
  releaseInactiveLogSinks(ev_now(getLoop()));
@@ -747,13 +747,13 @@ private:
747
747
  return sinkFlushInterval;
748
748
  }
749
749
  }
750
-
750
+
751
751
  void sinkFlushTimeout(ev::timer &timer, int revents) {
752
752
  P_DEBUG("Flushing all sinks");
753
753
  LogSinkCache::iterator it;
754
754
  LogSinkCache::iterator end = logSinkCache.end();
755
755
  ev_tstamp now = ev_now(getLoop());
756
-
756
+
757
757
  for (it = logSinkCache.begin(); it != end; it++) {
758
758
  LogSink *sink = it->second.get();
759
759
  if (now - sink->lastFlushed >= getFlushInterval(sink)) {
@@ -761,18 +761,18 @@ private:
761
761
  }
762
762
  }
763
763
  }
764
-
764
+
765
765
  void flushAllSinks() {
766
766
  P_TRACE(2, "Flushing all sinks");
767
767
  LogSinkCache::iterator it;
768
768
  LogSinkCache::iterator end = logSinkCache.end();
769
-
769
+
770
770
  for (it = logSinkCache.begin(); it != end; it++) {
771
771
  LogSink *sink = it->second.get();
772
772
  sink->flush();
773
773
  }
774
774
  }
775
-
775
+
776
776
  void exitTimerTimeout(ev::timer &timer, int revents) {
777
777
  if (SystemTime::getMsec() >= exitBeginTime + 5000) {
778
778
  exitTimer.stop();
@@ -781,24 +781,24 @@ private:
781
781
  ev_break(getLoop(), EVBREAK_ONE);
782
782
  }
783
783
  }
784
-
784
+
785
785
  protected:
786
786
  virtual EventedClient *createClient(const FileDescriptor &fd) {
787
787
  return new Client(getLoop(), fd);
788
788
  }
789
-
789
+
790
790
  virtual bool onMessageReceived(EventedMessageClient *_client, const vector<StaticString> &args) {
791
791
  Client *client = (Client *) _client;
792
-
792
+
793
793
  if (args[0] == "log") {
794
794
  if (OXT_UNLIKELY( !expectingArgumentsCount(client, args, 3)
795
795
  || !expectingLoggerType(client) )) {
796
796
  return true;
797
797
  }
798
-
798
+
799
799
  string txnId = args[1];
800
800
  string timestamp = args[2];
801
-
801
+
802
802
  TransactionMap::iterator it = transactions.find(txnId);
803
803
  if (OXT_UNLIKELY( it == transactions.end() )) {
804
804
  sendErrorToClient(client, "Cannot log data: transaction does not exist");
@@ -816,13 +816,13 @@ protected:
816
816
  client->currentTimestamp = timestamp;
817
817
  return false;
818
818
  }
819
-
819
+
820
820
  } else if (args[0] == "openTransaction") {
821
821
  if (OXT_UNLIKELY( !expectingMinArgumentsCount(client, args, 7)
822
822
  || !expectingLoggerType(client) )) {
823
823
  return true;
824
824
  }
825
-
825
+
826
826
  string txnId = args[1];
827
827
  StaticString groupName = args[2];
828
828
  StaticString nodeName = args[3];
@@ -832,7 +832,7 @@ protected:
832
832
  bool crashProtect = getBool(args, 7, true);
833
833
  bool ack = getBool(args, 8, false);
834
834
  StaticString filters = getStaticString(args, 9);
835
-
835
+
836
836
  if (OXT_UNLIKELY( !validTxnId(txnId) )) {
837
837
  sendErrorToClient(client, "Invalid transaction ID format");
838
838
  client->disconnect();
@@ -851,16 +851,16 @@ protected:
851
851
  client->disconnect();
852
852
  return true;
853
853
  }
854
-
854
+
855
855
  const char *nodeId;
856
-
856
+
857
857
  if (nodeName.empty()) {
858
858
  nodeName = client->nodeName;
859
859
  nodeId = client->nodeId;
860
860
  } else {
861
861
  nodeId = NULL;
862
862
  }
863
-
863
+
864
864
  TransactionMap::iterator it = transactions.find(txnId);
865
865
  TransactionPtr transaction;
866
866
  if (it == transactions.end()) {
@@ -869,11 +869,11 @@ protected:
869
869
  client->disconnect();
870
870
  return true;
871
871
  }
872
-
872
+
873
873
  transaction = boost::make_shared<Transaction>(this, ev_now(getLoop()));
874
874
  if (unionStationKey.empty() || unionStationKey == "-") {
875
875
  char tempNodeId[MD5_HEX_SIZE];
876
-
876
+
877
877
  if (nodeId == NULL) {
878
878
  md5_state_t state;
879
879
  md5_byte_t digest[MD5_SIZE];
@@ -887,7 +887,7 @@ protected:
887
887
  tempNodeId);
888
888
  nodeId = tempNodeId;
889
889
  }
890
-
890
+
891
891
  transaction->logSink = openLogFile();
892
892
  } else {
893
893
  transaction->logSink = openRemoteSink(unionStationKey,
@@ -927,25 +927,25 @@ protected:
927
927
  return true;
928
928
  }
929
929
  }
930
-
930
+
931
931
  client->openTransactions.insert(txnId);
932
932
  transaction->refcount++;
933
933
  writeLogEntry(client, transaction, timestamp, "ATTACH");
934
-
934
+
935
935
  if (ack) {
936
936
  client->writeArrayMessage("ok", NULL);
937
937
  }
938
-
938
+
939
939
  } else if (args[0] == "closeTransaction") {
940
940
  if (OXT_UNLIKELY( !expectingMinArgumentsCount(client, args, 3)
941
941
  || !expectingLoggerType(client) )) {
942
942
  return true;
943
943
  }
944
-
944
+
945
945
  string txnId = args[1];
946
946
  StaticString timestamp = args[2];
947
947
  bool ack = getBool(args, 3, false);
948
-
948
+
949
949
  TransactionMap::iterator it = transactions.find(txnId);
950
950
  if (OXT_UNLIKELY( it == transactions.end() )) {
951
951
  sendErrorToClient(client,
@@ -954,7 +954,7 @@ protected:
954
954
  client->disconnect();
955
955
  } else {
956
956
  TransactionPtr &transaction = it->second;
957
-
957
+
958
958
  set<string>::const_iterator sit = client->openTransactions.find(txnId);
959
959
  if (OXT_UNLIKELY( sit == client->openTransactions.end() )) {
960
960
  sendErrorToClient(client,
@@ -965,7 +965,7 @@ protected:
965
965
  } else {
966
966
  client->openTransactions.erase(sit);
967
967
  }
968
-
968
+
969
969
  writeDetachEntry(client, transaction, timestamp);
970
970
  transaction->refcount--;
971
971
  assert(transaction->refcount >= 0);
@@ -973,11 +973,11 @@ protected:
973
973
  transactions.erase(it);
974
974
  }
975
975
  }
976
-
976
+
977
977
  if (ack) {
978
978
  client->writeArrayMessage("ok", NULL);
979
979
  }
980
-
980
+
981
981
  } else if (args[0] == "init") {
982
982
  if (OXT_UNLIKELY( client->type != UNINITIALIZED )) {
983
983
  sendErrorToClient(client, "Already initialized");
@@ -990,32 +990,32 @@ protected:
990
990
  if (OXT_UNLIKELY( !checkWhetherConnectionAreAcceptable(client) )) {
991
991
  return true;
992
992
  }
993
-
993
+
994
994
  StaticString nodeName = args[1];
995
995
  client->nodeName = nodeName;
996
-
996
+
997
997
  md5_state_t state;
998
998
  md5_byte_t digest[MD5_SIZE];
999
999
  md5_init(&state);
1000
1000
  md5_append(&state, (const md5_byte_t *) nodeName.data(), nodeName.size());
1001
1001
  md5_finish(&state, digest);
1002
1002
  toHex(StaticString((const char *) digest, MD5_SIZE), client->nodeId);
1003
-
1003
+
1004
1004
  client->type = LOGGER;
1005
1005
  client->writeArrayMessage("ok", NULL);
1006
-
1006
+
1007
1007
  } else if (args[0] == "flush") {
1008
1008
  flushAllSinks();
1009
1009
  client->writeArrayMessage("ok", NULL);
1010
-
1010
+
1011
1011
  } else if (args[0] == "info") {
1012
1012
  stringstream stream;
1013
1013
  dump(stream);
1014
1014
  client->writeArrayMessage("info", stream.str().c_str(), NULL);
1015
-
1015
+
1016
1016
  } else if (args[0] == "ping") {
1017
1017
  client->writeArrayMessage("pong", NULL);
1018
-
1018
+
1019
1019
  } else if (args[0] == "exit") {
1020
1020
  if (!requireRights(client, Account::EXIT)) {
1021
1021
  client->disconnect();
@@ -1037,15 +1037,15 @@ protected:
1037
1037
  exitRequested = true;
1038
1038
  }
1039
1039
  client->disconnect();
1040
-
1040
+
1041
1041
  } else {
1042
1042
  sendErrorToClient(client, "Unknown command '" + args[0] + "'");
1043
1043
  client->disconnect();
1044
1044
  }
1045
-
1045
+
1046
1046
  return true;
1047
1047
  }
1048
-
1048
+
1049
1049
  virtual pair<size_t, bool> onOtherDataReceived(EventedMessageClient *_client,
1050
1050
  const char *data, size_t size)
1051
1051
  {
@@ -1065,20 +1065,20 @@ protected:
1065
1065
  return make_pair(consumed, false);
1066
1066
  }
1067
1067
  }
1068
-
1068
+
1069
1069
  virtual void onNewClient(EventedClient *client) {
1070
1070
  if (exitRequested && exitTimer.is_active()) {
1071
1071
  exitTimer.stop();
1072
1072
  }
1073
1073
  EventedMessageServer::onNewClient(client);
1074
1074
  }
1075
-
1075
+
1076
1076
  virtual void onClientDisconnected(EventedClient *_client) {
1077
1077
  EventedMessageServer::onClientDisconnected(_client);
1078
1078
  Client *client = (Client *) _client;
1079
1079
  set<string>::const_iterator sit;
1080
1080
  set<string>::const_iterator send = client->openTransactions.end();
1081
-
1081
+
1082
1082
  // Close any transactions that this client had opened.
1083
1083
  for (sit = client->openTransactions.begin(); sit != send; sit++) {
1084
1084
  const string &txnId = *sit;
@@ -1087,7 +1087,7 @@ protected:
1087
1087
  P_ERROR("Bug: client->openTransactions is not a subset of this->transactions!");
1088
1088
  abort();
1089
1089
  }
1090
-
1090
+
1091
1091
  TransactionPtr &transaction = it->second;
1092
1092
  if (transaction->crashProtect) {
1093
1093
  writeDetachEntry(client, transaction);
@@ -1101,7 +1101,7 @@ protected:
1101
1101
  }
1102
1102
  }
1103
1103
  client->openTransactions.clear();
1104
-
1104
+
1105
1105
  // Possibly start exit timer.
1106
1106
  if (exitRequested && getClients().empty()) {
1107
1107
  exitTimer.start();
@@ -1141,7 +1141,7 @@ public:
1141
1141
  exitRequested = false;
1142
1142
  inactiveLogSinksCount = 0;
1143
1143
  }
1144
-
1144
+
1145
1145
  ~LoggingServer() {
1146
1146
  TransactionMap::iterator it, end = transactions.end();
1147
1147
  for (it = transactions.begin(); it != end; it++) {
@@ -1152,18 +1152,18 @@ public:
1152
1152
  transaction->discard();
1153
1153
  }
1154
1154
  }
1155
-
1155
+
1156
1156
  // Invoke destructors, causing all transactions and log sinks to
1157
1157
  // be flushed before RemoteSender is being destroyed.
1158
1158
  transactions.clear();
1159
1159
  logSinkCache.clear();
1160
1160
  inactiveLogSinks.clear();
1161
1161
  }
1162
-
1162
+
1163
1163
  void dump(ostream &stream) const {
1164
1164
  TransactionMap::const_iterator it;
1165
1165
  TransactionMap::const_iterator end = transactions.end();
1166
-
1166
+
1167
1167
  ClientSet::const_iterator cit, cend = getClients().end();
1168
1168
  stream << "Clients:\n";
1169
1169
  stream << " Count: " << getClients().size() << "\n";