passenger 3.0.6 → 3.0.7

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/NEWS CHANGED
@@ -1,3 +1,24 @@
1
+ Release 3.0.7
2
+ -------------
3
+
4
+ * Fixed a bug passenger-install-apache2-module. It could crash on
5
+ some systems due to a typo in the code.
6
+ * Upgraded preferred Nginx version to 1.0.0.
7
+ * Phusion Passenger Standalone now pre-starts application processes
8
+ at startup instead of doing that at the first request.
9
+ * When sending data to Union Station, the HTTP status code is now also
10
+ logged.
11
+ * Various Union Station-related stability improvements.
12
+ * The Linux OOM killer was previously erroneously disabled for all
13
+ Phusion Passenger processes, including application processes. The
14
+ intention was to only disable it for the Watchdog. This has been
15
+ fixed, and the Watchdog is now the only process for which the OOM
16
+ killer is disabled.
17
+ * Fixed some compilation problems on OpenBSD.
18
+ * Due to a typo, the dependency on file-tail was not entirely removed
19
+ in 3.0.6. This has now been fixed.
20
+
21
+
1
22
  Release 3.0.6
2
23
  -------------
3
24
 
@@ -45,7 +45,6 @@ dependencies = [
45
45
  'ext/common/LoggingAgent/Main.cpp',
46
46
  'ext/common/LoggingAgent/LoggingServer.h',
47
47
  'ext/common/LoggingAgent/RemoteSender.h',
48
- 'ext/common/LoggingAgent/ChangeNotifier.h',
49
48
  'ext/common/LoggingAgent/DataStoreId.h',
50
49
  'ext/common/LoggingAgent/FilterSupport.h',
51
50
  'ext/common/ServerInstanceDir.h',
@@ -132,7 +132,6 @@ TEST_CXX_OBJECTS = {
132
132
  test/cxx/LoggingTest.cpp
133
133
  ext/common/LoggingAgent/LoggingServer.h
134
134
  ext/common/LoggingAgent/RemoteSender.h
135
- ext/common/LoggingAgent/ChangeNotifier.h
136
135
  ext/common/LoggingAgent/DataStoreId.h
137
136
  ext/common/LoggingAgent/FilterSupport.h
138
137
  ext/common/Logging.h
@@ -4514,7 +4514,7 @@ has no effect.</p></div>
4514
4514
  <div id="footnotes"><hr /></div>
4515
4515
  <div id="footer">
4516
4516
  <div id="footer-text">
4517
- Last updated 2010-12-05 20:52:52 CET
4517
+ Last updated 2011-04-06 13:32:49 CEST
4518
4518
  </div>
4519
4519
  </div>
4520
4520
  </body>
@@ -51,7 +51,7 @@
51
51
  <a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_CONSTANTS_H_</span>
52
52
  <a name="l00027"></a>00027 <span class="preprocessor"></span>
53
53
  <a name="l00028"></a>00028 <span class="comment">/* Don&#39;t forget to update lib/phusion_passenger.rb too. */</span>
54
- <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.6&quot;</span>
54
+ <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.7&quot;</span>
55
55
  <a name="l00030"></a>00030 <span class="preprocessor"></span>
56
56
  <a name="l00031"></a>00031 <span class="preprocessor">#define FEEDBACK_FD 3</span>
57
57
  <a name="l00032"></a>00032 <span class="preprocessor"></span>
@@ -53,13 +53,14 @@
53
53
  <a name="l00028"></a>00028 <span class="preprocessor">#ifndef _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_</span>
54
54
  <a name="l00029"></a>00029 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_</span>
55
55
  <a name="l00030"></a>00030 <span class="preprocessor"></span>
56
- <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;ngx_core.h&gt;</span>
57
- <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;ngx_http.h&gt;</span>
58
- <a name="l00033"></a>00033
59
- <a name="l00034"></a>00034 ngx_int_t passenger_static_content_handler(ngx_http_request_t *r,
60
- <a name="l00035"></a>00035 ngx_str_t *filename);
61
- <a name="l00036"></a>00036
62
- <a name="l00037"></a>00037 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_ */</span>
56
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;ngx_config.h&gt;</span>
57
+ <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;ngx_core.h&gt;</span>
58
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &lt;ngx_http.h&gt;</span>
59
+ <a name="l00034"></a>00034
60
+ <a name="l00035"></a>00035 ngx_int_t passenger_static_content_handler(ngx_http_request_t *r,
61
+ <a name="l00036"></a>00036 ngx_str_t *filename);
62
+ <a name="l00037"></a>00037
63
+ <a name="l00038"></a>00038 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_ */</span>
63
64
  </pre></div></div>
64
65
  <hr size="1"/><address style="text-align: right;"><small>Generated by&nbsp;
65
66
  <a href="http://www.doxygen.org/index.html">
Binary file
@@ -26,7 +26,7 @@ Collaboration diagram for Core Apache-related classes and functions:</div>
26
26
  <div class="dynsection">
27
27
  <center><table><tr><td><img src="group__Core.png" border="0" alt="" usemap="#group____Core_map"/>
28
28
  <map name="group____Core_map" id="group____Core">
29
- <area shape="rect" id="node2" href="group__Hooks.html" title="Apache hooks" alt="" coords="349,5,461,35"/></map></td></tr></table></center>
29
+ <area shape="rect" id="node2" href="group__Hooks.html" title="Apache hooks" alt="" coords="303,5,399,33"/></map></td></tr></table></center>
30
30
  </div>
31
31
  </p>
32
32
  <table border="0" cellpadding="0" cellspacing="0">
@@ -1,3 +1,3 @@
1
1
  <map id="structs" name="structs">
2
- <area shape="rect" id="node2" href="$group__Hooks.html" title="Apache hooks" alt="" coords="349,5,461,35"/>
2
+ <area shape="rect" id="node2" href="$group__Hooks.html" title="Apache hooks" alt="" coords="303,5,399,33"/>
3
3
  </map>
Binary file
@@ -29,7 +29,7 @@ Collaboration diagram for Apache hooks:</div>
29
29
  <div class="dynsection">
30
30
  <center><table><tr><td><img src="group__Hooks.png" border="0" alt="" usemap="#group____Hooks_map"/>
31
31
  <map name="group____Hooks_map" id="group____Hooks">
32
- <area shape="rect" id="node1" href="group__Core.html" title="Core Apache&#45;related classes and functions" alt="" coords="7,5,300,35"/></map></td></tr></table></center>
32
+ <area shape="rect" id="node1" href="group__Core.html" title="Core Apache&#45;related classes and functions" alt="" coords="5,5,253,33"/></map></td></tr></table></center>
33
33
  </div>
34
34
  </p>
35
35
  <table border="0" cellpadding="0" cellspacing="0">
@@ -1,3 +1,3 @@
1
1
  <map id="structs" name="structs">
2
- <area shape="rect" id="node1" href="$group__Core.html" title="Core Apache&#45;related classes and functions" alt="" coords="7,5,300,35"/>
2
+ <area shape="rect" id="node1" href="$group__Core.html" title="Core Apache&#45;related classes and functions" alt="" coords="5,5,253,33"/>
3
3
  </map>
Binary file
@@ -53,39 +53,40 @@
53
53
  <a name="l00028"></a>00028 <span class="preprocessor">#ifndef _PASSENGER_NGINX_MODULE_H_</span>
54
54
  <a name="l00029"></a>00029 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_NGINX_MODULE_H_</span>
55
55
  <a name="l00030"></a>00030 <span class="preprocessor"></span>
56
- <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;ngx_core.h&gt;</span>
57
- <a name="l00032"></a>00032 <span class="preprocessor">#include &quot;../common/AgentsStarter.h&quot;</span>
58
- <a name="l00033"></a>00033 <span class="preprocessor">#include &quot;../common/Utils/CachedFileStat.h&quot;</span>
59
- <a name="l00034"></a>00034 <span class="comment"></span>
60
- <a name="l00035"></a>00035 <span class="comment">/**</span>
61
- <a name="l00036"></a>00036 <span class="comment"> * The Nginx version number as an integer.</span>
62
- <a name="l00037"></a>00037 <span class="comment"> * For example, on nginx 1.7.30 this value is 1007030.</span>
63
- <a name="l00038"></a>00038 <span class="comment"> */</span>
64
- <a name="l00039"></a>00039 <span class="preprocessor">#define NGINX_VERSION_NUM \</span>
65
- <a name="l00040"></a>00040 <span class="preprocessor"> (1000000 * PASSENGER_NGINX_MAJOR_VERSION + \</span>
66
- <a name="l00041"></a>00041 <span class="preprocessor"> 1000 * PASSENGER_NGINX_MINOR_VERSION + \</span>
67
- <a name="l00042"></a>00042 <span class="preprocessor"> PASSENGER_NGINX_MICRO_VERSION)</span>
68
- <a name="l00043"></a>00043 <span class="preprocessor"></span>
69
- <a name="l00044"></a>00044 <span class="keyword">extern</span> ngx_module_t ngx_http_passenger_module;
70
- <a name="l00045"></a>00045 <span class="comment"></span>
71
- <a name="l00046"></a>00046 <span class="comment">/**</span>
72
- <a name="l00047"></a>00047 <span class="comment"> * A static schema string to be assigned to Nginx &#39;upstream&#39; strctures.</span>
73
- <a name="l00048"></a>00048 <span class="comment"> */</span>
74
- <a name="l00049"></a>00049 <span class="keyword">extern</span> ngx_str_t passenger_schema_string;
75
- <a name="l00050"></a>00050
76
- <a name="l00051"></a>00051 <span class="keyword">extern</span> ngx_str_t passenger_placeholder_upstream_address;
77
- <a name="l00052"></a>00052 <span class="comment"></span>
78
- <a name="l00053"></a>00053 <span class="comment">/**</span>
79
- <a name="l00054"></a>00054 <span class="comment"> * A CachedFileStat object used for caching stat() calls.</span>
80
- <a name="l00055"></a>00055 <span class="comment"> */</span>
81
- <a name="l00056"></a>00056 <span class="keyword">extern</span> PassengerCachedFileStat *passenger_stat_cache;
82
- <a name="l00057"></a>00057
83
- <a name="l00058"></a>00058 <span class="keyword">extern</span> AgentsStarter *passenger_agents_starter;
84
- <a name="l00059"></a>00059
85
- <a name="l00060"></a>00060 <span class="keyword">extern</span> ngx_cycle_t *passenger_current_cycle;
86
- <a name="l00061"></a>00061
87
- <a name="l00062"></a>00062 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_NGINX_MODULE_H_ */</span>
88
- <a name="l00063"></a>00063
56
+ <a name="l00031"></a>00031 <span class="preprocessor">#include &lt;ngx_config.h&gt;</span>
57
+ <a name="l00032"></a>00032 <span class="preprocessor">#include &lt;ngx_core.h&gt;</span>
58
+ <a name="l00033"></a>00033 <span class="preprocessor">#include &quot;../common/AgentsStarter.h&quot;</span>
59
+ <a name="l00034"></a>00034 <span class="preprocessor">#include &quot;../common/Utils/CachedFileStat.h&quot;</span>
60
+ <a name="l00035"></a>00035 <span class="comment"></span>
61
+ <a name="l00036"></a>00036 <span class="comment">/**</span>
62
+ <a name="l00037"></a>00037 <span class="comment"> * The Nginx version number as an integer.</span>
63
+ <a name="l00038"></a>00038 <span class="comment"> * For example, on nginx 1.7.30 this value is 1007030.</span>
64
+ <a name="l00039"></a>00039 <span class="comment"> */</span>
65
+ <a name="l00040"></a>00040 <span class="preprocessor">#define NGINX_VERSION_NUM \</span>
66
+ <a name="l00041"></a>00041 <span class="preprocessor"> (1000000 * PASSENGER_NGINX_MAJOR_VERSION + \</span>
67
+ <a name="l00042"></a>00042 <span class="preprocessor"> 1000 * PASSENGER_NGINX_MINOR_VERSION + \</span>
68
+ <a name="l00043"></a>00043 <span class="preprocessor"> PASSENGER_NGINX_MICRO_VERSION)</span>
69
+ <a name="l00044"></a>00044 <span class="preprocessor"></span>
70
+ <a name="l00045"></a>00045 <span class="keyword">extern</span> ngx_module_t ngx_http_passenger_module;
71
+ <a name="l00046"></a>00046 <span class="comment"></span>
72
+ <a name="l00047"></a>00047 <span class="comment">/**</span>
73
+ <a name="l00048"></a>00048 <span class="comment"> * A static schema string to be assigned to Nginx &#39;upstream&#39; strctures.</span>
74
+ <a name="l00049"></a>00049 <span class="comment"> */</span>
75
+ <a name="l00050"></a>00050 <span class="keyword">extern</span> ngx_str_t passenger_schema_string;
76
+ <a name="l00051"></a>00051
77
+ <a name="l00052"></a>00052 <span class="keyword">extern</span> ngx_str_t passenger_placeholder_upstream_address;
78
+ <a name="l00053"></a>00053 <span class="comment"></span>
79
+ <a name="l00054"></a>00054 <span class="comment">/**</span>
80
+ <a name="l00055"></a>00055 <span class="comment"> * A CachedFileStat object used for caching stat() calls.</span>
81
+ <a name="l00056"></a>00056 <span class="comment"> */</span>
82
+ <a name="l00057"></a>00057 <span class="keyword">extern</span> PassengerCachedFileStat *passenger_stat_cache;
83
+ <a name="l00058"></a>00058
84
+ <a name="l00059"></a>00059 <span class="keyword">extern</span> AgentsStarter *passenger_agents_starter;
85
+ <a name="l00060"></a>00060
86
+ <a name="l00061"></a>00061 <span class="keyword">extern</span> ngx_cycle_t *passenger_current_cycle;
87
+ <a name="l00062"></a>00062
88
+ <a name="l00063"></a>00063 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_NGINX_MODULE_H_ */</span>
89
+ <a name="l00064"></a>00064
89
90
  </pre></div></div>
90
91
  <hr size="1"/><address style="text-align: right;"><small>Generated by&nbsp;
91
92
  <a href="http://www.doxygen.org/index.html">
@@ -770,6 +770,7 @@ private:
770
770
  r->status);
771
771
  }
772
772
  apr_table_setn(r->headers_out, "Status", r->status_line);
773
+ log->message(string("Status: ") + r->status_line);
773
774
 
774
775
  bool xsendfile = hasModXsendfile() &&
775
776
  apr_table_get(r->err_headers_out, "X-Sendfile");
@@ -154,8 +154,12 @@ appendSignalReason(char *buf, siginfo_t *info) {
154
154
  #endif
155
155
  SI_CODE_HANDLER(SI_QUEUE);
156
156
  SI_CODE_HANDLER(SI_TIMER);
157
- SI_CODE_HANDLER(SI_ASYNCIO);
158
- SI_CODE_HANDLER(SI_MESGQ);
157
+ #ifdef SI_ASYNCIO
158
+ SI_CODE_HANDLER(SI_ASYNCIO);
159
+ #endif
160
+ #ifdef SI_MESGQ
161
+ SI_CODE_HANDLER(SI_MESGQ);
162
+ #endif
159
163
  #ifdef SI_SIGIO
160
164
  SI_CODE_HANDLER(SI_SIGIO);
161
165
  #endif
@@ -26,7 +26,7 @@
26
26
  #define _PASSENGER_CONSTANTS_H_
27
27
 
28
28
  /* Don't forget to update lib/phusion_passenger.rb too. */
29
- #define PASSENGER_VERSION "3.0.6"
29
+ #define PASSENGER_VERSION "3.0.7"
30
30
 
31
31
  #define FEEDBACK_FD 3
32
32
 
@@ -44,7 +44,6 @@
44
44
 
45
45
  #include "DataStoreId.h"
46
46
  #include "RemoteSender.h"
47
- #include "ChangeNotifier.h"
48
47
  #include "FilterSupport.h"
49
48
  #include "../EventedMessageServer.h"
50
49
  #include "../MessageReadersWriters.h"
@@ -121,7 +120,7 @@ private:
121
120
 
122
121
  virtual void append(const DataStoreId &dataStoreId,
123
122
  const StaticString &data) = 0;
124
- virtual void flush() { }
123
+ virtual bool flush() { return true; }
125
124
  virtual void dump(ostream &stream) const { }
126
125
  };
127
126
 
@@ -133,12 +132,6 @@ private:
133
132
  char buffer[BUFFER_CAPACITY];
134
133
  unsigned int bufferSize;
135
134
 
136
- /**
137
- * Contains every (groupName, nodeName, category) tuple for
138
- * which their data is currently buffered in this sink.
139
- */
140
- set<DataStoreId> dataStoreIds;
141
-
142
135
  LogFile(LoggingServer *server, const string &filename, mode_t filePermissions)
143
136
  : LogSink(server)
144
137
  {
@@ -163,22 +156,7 @@ private:
163
156
  flush();
164
157
  }
165
158
 
166
- void notifyChanges() {
167
- if (server->changeNotifier != NULL) {
168
- set<DataStoreId>::const_iterator it;
169
- set<DataStoreId>::const_iterator end = dataStoreIds.end();
170
-
171
- for (it = dataStoreIds.begin(); it != dataStoreIds.end(); it++) {
172
- server->changeNotifier->changed(*it);
173
- }
174
- }
175
- dataStoreIds.clear();
176
- }
177
-
178
159
  virtual void append(const DataStoreId &dataStoreId, const StaticString &data) {
179
- if (server->changeNotifier != NULL) {
180
- dataStoreIds.insert(dataStoreId);
181
- }
182
160
  if (bufferSize + data.size() > BUFFER_CAPACITY) {
183
161
  StaticString data2[2];
184
162
  data2[0] = StaticString(buffer, bufferSize);
@@ -187,19 +165,20 @@ private:
187
165
  gatheredWrite(fd, data2, 2);
188
166
  lastFlushed = ev_now(server->getLoop());
189
167
  bufferSize = 0;
190
- notifyChanges();
191
168
  } else {
192
169
  memcpy(buffer + bufferSize, data.data(), data.size());
193
170
  bufferSize += data.size();
194
171
  }
195
172
  }
196
173
 
197
- virtual void flush() {
174
+ virtual bool flush() {
198
175
  if (bufferSize > 0) {
199
176
  lastFlushed = ev_now(server->getLoop());
200
177
  writeExact(fd, buffer, bufferSize);
201
178
  bufferSize = 0;
202
- notifyChanges();
179
+ return true;
180
+ } else {
181
+ return false;
203
182
  }
204
183
  }
205
184
 
@@ -270,13 +249,16 @@ private:
270
249
  }
271
250
  }
272
251
 
273
- virtual void flush() {
252
+ virtual bool flush() {
274
253
  if (bufferSize > 0) {
275
254
  lastFlushed = ev_now(server->getLoop());
276
255
  StaticString data(buffer, bufferSize);
277
256
  server->remoteSender.schedule(unionStationKey, nodeName,
278
257
  category, &data, 1);
279
258
  bufferSize = 0;
259
+ return true;
260
+ } else {
261
+ return false;
280
262
  }
281
263
  }
282
264
 
@@ -376,8 +358,7 @@ private:
376
358
 
377
359
  enum ClientType {
378
360
  UNINITIALIZED,
379
- LOGGER,
380
- WATCHER
361
+ LOGGER
381
362
  };
382
363
 
383
364
  struct Client: public EventedMessageClient {
@@ -411,7 +392,6 @@ private:
411
392
  string dirPermissions;
412
393
  mode_t filePermissions;
413
394
  RemoteSender remoteSender;
414
- ChangeNotifierPtr changeNotifier;
415
395
  ev::timer garbageCollectionTimer;
416
396
  ev::timer sinkFlushingTimer;
417
397
  ev::timer exitTimer;
@@ -820,58 +800,6 @@ private:
820
800
  return true;
821
801
  }
822
802
 
823
- bool getLastEntryInDirectory(const string &path, string &result) const {
824
- DIR *dir = opendir(path.c_str());
825
- struct dirent *entry;
826
- vector<string> subdirs;
827
-
828
- if (dir == NULL) {
829
- int e = errno;
830
- throw FileSystemException("Cannot open directory " + path,
831
- e, path);
832
- }
833
- while ((entry = readdir(dir)) != NULL) {
834
- if (isDirectory(path, entry) && looksLikeNumber(entry->d_name)) {
835
- subdirs.push_back(entry->d_name);
836
- }
837
- }
838
- closedir(dir);
839
-
840
- if (subdirs.empty()) {
841
- return false;
842
- }
843
-
844
- vector<string>::const_iterator it = subdirs.begin();
845
- vector<string>::const_iterator end = subdirs.end();
846
- vector<string>::const_iterator largest_it = subdirs.begin();
847
- int largest = atoi(subdirs[0]);
848
- for (it++; it != end; it++) {
849
- const string &subdir = *it;
850
- int number = atoi(subdir.c_str());
851
- if (number > largest) {
852
- largest_it = it;
853
- largest = number;
854
- }
855
- }
856
- result = *largest_it;
857
- return true;
858
- }
859
-
860
- static void pendingDataFlushed(EventedClient *_client) {
861
- Client *client = (Client *) _client;
862
- LoggingServer *self = (LoggingServer *) client->userData;
863
-
864
- client->onPendingDataFlushed = NULL;
865
- if (OXT_UNLIKELY( client->type != WATCHER )) {
866
- P_WARN("BUG: pendingDataFlushed() called even though client type is not WATCHER.");
867
- client->disconnect();
868
- } else if (self->changeNotifier != NULL) {
869
- self->changeNotifier->addClient(client->detach());
870
- } else {
871
- client->disconnect();
872
- }
873
- }
874
-
875
803
  /* Release all inactive log sinks that have been inactive for more than
876
804
  * GARBAGE_COLLECTION_TIMEOUT seconds.
877
805
  */
@@ -1160,26 +1088,6 @@ protected:
1160
1088
  client->type = LOGGER;
1161
1089
  client->writeArrayMessage("ok", NULL);
1162
1090
 
1163
- } else if (args[0] == "watchChanges") {
1164
- if (OXT_UNLIKELY( !checkWhetherConnectionAreAcceptable(client) )) {
1165
- return true;
1166
- }
1167
- if (OXT_UNLIKELY( client->type != UNINITIALIZED )) {
1168
- sendErrorToClient(client, "This command cannot be invoked "
1169
- "if the 'init' command is already invoked.");
1170
- client->disconnect();
1171
- return true;
1172
- }
1173
-
1174
- client->type = WATCHER;
1175
- client->notifyReads(false);
1176
- discardReadData();
1177
-
1178
- // Add to the change notifier after all pending data
1179
- // has been written out.
1180
- client->onPendingDataFlushed = pendingDataFlushed;
1181
- client->writeArrayMessage("ok", NULL);
1182
-
1183
1091
  } else if (args[0] == "flush") {
1184
1092
  flushAllSinks();
1185
1093
  client->writeArrayMessage("ok", NULL);
@@ -1334,79 +1242,18 @@ public:
1334
1242
  }
1335
1243
 
1336
1244
  // Invoke destructors, causing all transactions and log sinks to
1337
- // be flushed before RemoteSender and ChangeNotifier are being
1338
- // destroyed.
1245
+ // be flushed before RemoteSender is being destroyed.
1339
1246
  transactions.clear();
1340
1247
  logSinkCache.clear();
1341
1248
  inactiveLogSinks.clear();
1342
1249
  }
1343
1250
 
1344
- void setChangeNotifier(const ChangeNotifierPtr &_changeNotifier) {
1345
- changeNotifier = _changeNotifier;
1346
- changeNotifier->getLastPos = boost::bind(&LoggingServer::getLastPos,
1347
- this, _1, _2, _3);
1348
- }
1349
-
1350
- string getLastPos(const StaticString &groupName, const StaticString &nodeName,
1351
- const StaticString &category) const
1352
- {
1353
- md5_state_t state;
1354
- md5_byte_t digest[MD5_SIZE];
1355
- char nodeId[MD5_HEX_SIZE];
1356
- md5_init(&state);
1357
- md5_append(&state, (const md5_byte_t *) nodeName.data(), nodeName.size());
1358
- md5_finish(&state, digest);
1359
- toHex(StaticString((const char *) digest, MD5_SIZE), nodeId);
1360
-
1361
- string dir = determineFilename(groupName, nodeId, category);
1362
- string subdir, component;
1363
- subdir.reserve(13); // It's a string that looks like: "2010/06/24/12"
1364
-
1365
- try {
1366
- // Loop 4 times to process year, month, day, hour.
1367
- for (int i = 0; i < 4; i++) {
1368
- bool found = getLastEntryInDirectory(dir, component);
1369
- if (!found) {
1370
- return string();
1371
- }
1372
- dir.append("/");
1373
- dir.append(component);
1374
- if (i != 0) {
1375
- subdir.append("/");
1376
- }
1377
- subdir.append(component);
1378
- }
1379
- // After the loop, new dir == old dir + "/" + subdir
1380
- } catch (const SystemException &e) {
1381
- if (e.code() == ENOENT) {
1382
- return string();
1383
- } else {
1384
- throw;
1385
- }
1386
- }
1387
-
1388
- string &filename = dir;
1389
- filename.append("/log.txt");
1390
-
1391
- struct stat buf;
1392
- if (stat(filename.c_str(), &buf) == -1) {
1393
- if (errno == ENOENT) {
1394
- return string();
1395
- } else {
1396
- int e = errno;
1397
- throw FileSystemException("Cannot stat() " + filename, e,
1398
- filename);
1399
- }
1400
- } else {
1401
- return subdir + "/" + toString(buf.st_size);
1402
- }
1403
- }
1404
-
1405
1251
  void dump(ostream &stream) const {
1406
1252
  TransactionMap::const_iterator it;
1407
1253
  TransactionMap::const_iterator end = transactions.end();
1408
1254
 
1409
- stream << "Number of clients: " << getClients().size() << "\n";
1255
+ stream << "Number of clients : " << getClients().size() << "\n";
1256
+ stream << "RemoteSender queue: " << remoteSender.queued() << " items\n";
1410
1257
  stream << "Open transactions: " << transactions.size() << "\n";
1411
1258
  for (it = transactions.begin(); it != end; it++) {
1412
1259
  const TransactionPtr &transaction = it->second;
@@ -97,6 +97,8 @@ private:
97
97
  throw IOException("Unable to create a CURL handle");
98
98
  }
99
99
  }
100
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
101
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);
100
102
  curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, lastErrorMessage);
101
103
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
102
104
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlDataReceived);
@@ -467,7 +469,13 @@ public:
467
469
  }
468
470
  }
469
471
 
470
- queue.add(item);
472
+ if (!queue.tryAdd(item)) {
473
+ P_WARN("The Union Station gateway isn't responding quickly enough; dropping packet.");
474
+ }
475
+ }
476
+
477
+ unsigned int queued() const {
478
+ return queue.size();
471
479
  }
472
480
  };
473
481
 
@@ -37,7 +37,7 @@ using namespace boost;
37
37
  template<typename T>
38
38
  class BlockingQueue {
39
39
  private:
40
- timed_mutex lock;
40
+ mutable timed_mutex lock;
41
41
  condition_variable_any added;
42
42
  condition_variable_any removed;
43
43
  unsigned int max;
@@ -52,6 +52,11 @@ public:
52
52
  this->max = max;
53
53
  }
54
54
 
55
+ unsigned int size() const {
56
+ lock_guard<timed_mutex> l(lock);
57
+ return queue.size();
58
+ }
59
+
55
60
  void add(const T &item) {
56
61
  unique_lock<timed_mutex> l(lock);
57
62
  while (atMaxCapacity()) {
@@ -64,6 +69,20 @@ public:
64
69
  }
65
70
  }
66
71
 
72
+ bool tryAdd(const T &item) {
73
+ lock_guard<timed_mutex> l(lock);
74
+ if (!atMaxCapacity()) {
75
+ queue.push(item);
76
+ added.notify_one();
77
+ if (!atMaxCapacity()) {
78
+ removed.notify_one();
79
+ }
80
+ return true;
81
+ } else {
82
+ return false;
83
+ }
84
+ }
85
+
67
86
  T get() {
68
87
  unique_lock<timed_mutex> l(lock);
69
88
  while (queue.empty()) {
@@ -47,6 +47,7 @@
47
47
  #include "RandomGenerator.h"
48
48
  #include "Logging.h"
49
49
  #include "Exceptions.h"
50
+ #include "StaticString.h"
50
51
  #include "ResourceLocator.h"
51
52
  #include "Utils.h"
52
53
  #include "Utils/Base64.h"
@@ -79,6 +80,7 @@ static unsigned int maxInstancesPerApp;
79
80
  static unsigned int poolIdleTime;
80
81
  static string serializedPrestartURLs;
81
82
 
83
+ static string oldOomScore;
82
84
  static ServerInstanceDirPtr serverInstanceDir;
83
85
  static ServerInstanceDir::GenerationPtr generation;
84
86
  static string loggingAgentAddress;
@@ -88,6 +90,8 @@ static EventFd *errorEvent;
88
90
 
89
91
  #define REQUEST_SOCKET_PASSWORD_SIZE 64
90
92
 
93
+ static string setOomScore(const StaticString &score);
94
+
91
95
 
92
96
  /**
93
97
  * Abstract base class for watching agent processes.
@@ -100,7 +104,7 @@ private:
100
104
  void threadMain() {
101
105
  try {
102
106
  pid_t pid, ret;
103
- int status;
107
+ int status, e;
104
108
 
105
109
  while (!this_thread::interruption_requested()) {
106
110
  lock.lock();
@@ -123,6 +127,9 @@ private:
123
127
  P_WARN("waitpid() on " << name() << " return -1 with " <<
124
128
  "errno = ECHILD, falling back to kill polling");
125
129
  waitpidUsingKillPolling(pid);
130
+ e = 0;
131
+ } else {
132
+ e = errno;
126
133
  }
127
134
 
128
135
  lock.lock();
@@ -132,7 +139,6 @@ private:
132
139
  this_thread::disable_interruption di;
133
140
  this_thread::disable_syscall_interruption dsi;
134
141
  if (ret == -1) {
135
- int e = errno;
136
142
  P_WARN(name() << " crashed or killed for "
137
143
  "an unknown reason (errno = " <<
138
144
  strerror(e) << "), restarting it...");
@@ -345,6 +351,8 @@ public:
345
351
  * agent as well as all its descendant processes. */
346
352
  setpgid(getpid(), getpid());
347
353
 
354
+ setOomScore(oldOomScore);
355
+
348
356
  try {
349
357
  execProgram();
350
358
  } catch (...) {
@@ -715,6 +723,8 @@ private:
715
723
  _exit(1);
716
724
  }
717
725
 
726
+ setOomScore(oldOomScore);
727
+
718
728
  execlp("/bin/sh", "/bin/sh", "-c", "find . | xargs touch", (char *) 0);
719
729
  e = errno;
720
730
  fprintf(stderr, "Cannot execute 'find . | xargs touch': %s (%d)\n",
@@ -748,22 +758,44 @@ public:
748
758
 
749
759
 
750
760
  /**
751
- * Most operating systems overcommit memory. We *know* that this watchdog process
752
- * doesn't use much memory; on OS X it uses about 200 KB of private RSS. If the
753
- * watchdog is killed by the system Out-Of-Memory Killer or then it's all over:
754
- * the system administrator will have to restart the web server for Phusion
755
- * Passenger to be usable again. So in this function we do whatever is necessary
756
- * to prevent this watchdog process from becoming a candidate for the OS's
757
- * Out-Of-Memory Killer.
761
+ * Linux-only way to change OOM killer configuration for
762
+ * current process. Requires root privileges, which we
763
+ * should have.
758
764
  */
759
- static void
760
- disableOomKiller() {
761
- // Linux-only way to disable OOM killer for current process. Requires root
762
- // privileges, which we should have.
763
- FILE *f = fopen("/proc/self/oom_adj", "w");
764
- if (f != NULL) {
765
- fprintf(f, "-17");
765
+ static string
766
+ setOomScore(const StaticString &score) {
767
+ if (!score.empty()) {
768
+ string oldScore;
769
+
770
+ FILE *f = fopen("/proc/self/oom_adj", "r");
771
+ if (f == NULL) {
772
+ return "";
773
+ }
774
+ char buf[1024];
775
+ size_t bytesRead;
776
+ while (true) {
777
+ bytesRead = fread(buf, 1, sizeof(buf), f);
778
+ if (bytesRead == 0 && feof(f)) {
779
+ break;
780
+ } else if (bytesRead == 0 && ferror(f)) {
781
+ fclose(f);
782
+ return "";
783
+ } else {
784
+ oldScore.append(buf, bytesRead);
785
+ }
786
+ }
787
+ fclose(f);
788
+
789
+ f = fopen("/proc/self/oom_adj", "w");
790
+ if (f == NULL) {
791
+ return "";
792
+ }
793
+ fwrite(score.data(), 1, score.size(), f);
766
794
  fclose(f);
795
+
796
+ return oldScore;
797
+ } else {
798
+ return "";
767
799
  }
768
800
  }
769
801
 
@@ -917,7 +949,16 @@ forceAllAgentsShutdown(vector<AgentWatcher *> &watchers) {
917
949
 
918
950
  int
919
951
  main(int argc, char *argv[]) {
920
- disableOomKiller();
952
+ /*
953
+ * Most operating systems overcommit memory. We *know* that this watchdog process
954
+ * doesn't use much memory; on OS X it uses about 200 KB of private RSS. If the
955
+ * watchdog is killed by the system Out-Of-Memory Killer or then it's all over:
956
+ * the system administrator will have to restart the web server for Phusion
957
+ * Passenger to be usable again. So here we disable Linux's OOM killer
958
+ * for this watchdog. Note that the OOM score is inherited by child processes
959
+ * so we need to restore it after each fork().
960
+ */
961
+ oldOomScore = setOomScore("-17");
921
962
 
922
963
  agentsOptions = initializeAgent(argc, argv, "PassengerWatchdog");
923
964
  logLevel = agentsOptions.getInt("log_level");
@@ -313,7 +313,9 @@ private:
313
313
  * before we were able to send back the
314
314
  * full response.
315
315
  */
316
- void forwardResponse(SessionPtr &session, FileDescriptor &clientFd) {
316
+ void forwardResponse(SessionPtr &session, FileDescriptor &clientFd,
317
+ const AnalyticsLogPtr &log)
318
+ {
317
319
  TRACE_POINT();
318
320
  HttpStatusExtractor ex;
319
321
  int stream = session->getStream();
@@ -345,6 +347,11 @@ private:
345
347
  writeExact(clientFd, statusLine);
346
348
  UPDATE_TRACE_POINT();
347
349
  writeExact(clientFd, ex.getBuffer());
350
+ if (!log->isNull()) {
351
+ string partialStatusLine = ex.getStatusLine();
352
+ partialStatusLine.erase(partialStatusLine.size() - 2, 2);
353
+ log->message("Status: " + partialStatusLine);
354
+ }
348
355
  break;
349
356
  } catch (const SystemException &e) {
350
357
  if (e.code() == EPIPE) {
@@ -555,7 +562,7 @@ private:
555
562
  scope.success();
556
563
  }
557
564
 
558
- forwardResponse(session, clientFd);
565
+ forwardResponse(session, clientFd, log);
559
566
 
560
567
  requestProxyingScope.success();
561
568
  } catch (const SpawnException &e) {
@@ -28,6 +28,7 @@
28
28
  #ifndef _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_
29
29
  #define _PASSENGER_NGINX_STATIC_CONTENT_HANDLER_H_
30
30
 
31
+ #include <ngx_config.h>
31
32
  #include <ngx_core.h>
32
33
  #include <ngx_http.h>
33
34
 
@@ -28,6 +28,7 @@
28
28
  #ifndef _PASSENGER_NGINX_MODULE_H_
29
29
  #define _PASSENGER_NGINX_MODULE_H_
30
30
 
31
+ #include <ngx_config.h>
31
32
  #include <ngx_core.h>
32
33
  #include "../common/AgentsStarter.h"
33
34
  #include "../common/Utils/CachedFileStat.h"
@@ -25,10 +25,10 @@ module PhusionPassenger
25
25
  ###### Version numbers ######
26
26
 
27
27
  # Phusion Passenger version number. Don't forget to edit ext/common/Constants.h too.
28
- VERSION_STRING = '3.0.6'
28
+ VERSION_STRING = '3.0.7'
29
29
 
30
- PREFERRED_NGINX_VERSION = '0.8.54'
31
- PREFERRED_PCRE_VERSION = '8.10'
30
+ PREFERRED_NGINX_VERSION = '1.0.0'
31
+ PREFERRED_PCRE_VERSION = '8.12'
32
32
  STANDALONE_INTERFACE_VERSION = 1
33
33
 
34
34
 
@@ -274,7 +274,7 @@ module PlatformInfo
274
274
  # headers are placed into the same directory as the Apache headers,
275
275
  # and so 'apr-config' and 'apu-config' won't be necessary in that case.
276
276
  def self.apr_config_needed_for_building_apache_modules?
277
- filename = File.join("#{test_exe_outdir}/passenger-platform-check-#{Process.pid}.c")
277
+ filename = File.join("#{tmpexedir}/passenger-platform-check-#{Process.pid}.c")
278
278
  File.open(filename, "w") do |f|
279
279
  f.puts("#include <apr.h>")
280
280
  end
@@ -57,7 +57,6 @@ class StartCommand < Command
57
57
  sanity_check_options
58
58
 
59
59
  ensure_nginx_installed
60
- require_file_tail if should_watch_logs?
61
60
  determine_various_resource_locations
62
61
  require_app_finder
63
62
  @app_finder = AppFinder.new(@args, @options)
@@ -105,15 +104,6 @@ class StartCommand < Command
105
104
  end
106
105
 
107
106
  private
108
- def require_file_tail
109
- begin
110
- require 'file/tail'
111
- rescue LoadError
112
- error "Please install file-tail first: sudo gem install file-tail"
113
- exit 1
114
- end
115
- end
116
-
117
107
  def require_file_utils
118
108
  require 'fileutils' unless defined?(FileUtils)
119
109
  end
@@ -433,7 +423,6 @@ private
433
423
  end
434
424
 
435
425
  def watch_log_files_in_background
436
- require_file_tail
437
426
  @apps.each do |app|
438
427
  thread = Thread.new do
439
428
  watch_log_file("#{app[:root]}/log/#{@options[:env]}.log")
@@ -91,5 +91,6 @@ http {
91
91
  union_station_key <%= app[:union_station_key] %>;
92
92
  <% end %>
93
93
  }
94
+ passenger_pre_start http://<%= nginx_listen_address(app) %>;
94
95
  <% end %>
95
96
  }
@@ -114,33 +114,6 @@ namespace tut {
114
114
  }
115
115
  return client;
116
116
  }
117
-
118
- void setChangeNotifier(const ChangeNotifierPtr &notifier) {
119
- server->setChangeNotifier(notifier);
120
- }
121
-
122
-
123
- class MyChangeNotifier: public ChangeNotifier {
124
- public:
125
- boost::mutex lock;
126
- AtomicInt added;
127
- set<DataStoreId> changes;
128
-
129
- MyChangeNotifier(struct ev_loop *loop)
130
- : ChangeNotifier(loop)
131
- { }
132
-
133
- virtual void addClient(const FileDescriptor &fd) {
134
- added = added + 1;
135
- }
136
-
137
- virtual void changed(const DataStoreId &dataStoreId) {
138
- lock_guard<boost::mutex> l(lock);
139
- changes.insert(dataStoreId);
140
- }
141
- };
142
-
143
- typedef shared_ptr<MyChangeNotifier> MyChangeNotifierPtr;
144
117
  };
145
118
 
146
119
  DEFINE_TEST_GROUP(LoggingTest);
@@ -555,53 +528,6 @@ namespace tut {
555
528
  }
556
529
  }
557
530
 
558
- TEST_METHOD(19) {
559
- // getLastPos() works
560
- SystemTime::forceAll(YESTERDAY);
561
-
562
- AnalyticsLogPtr log = logger->newTransaction("foobar");
563
- log->message("hello world");
564
- log->flushToDiskAfterClose(true);
565
- log.reset();
566
-
567
- SystemTime::forceAll(TODAY);
568
-
569
- log = logger->newTransaction("foobar");
570
- log->message("hello world");
571
- log->flushToDiskAfterClose(true);
572
- log.reset();
573
-
574
- stopLoggingServer(false);
575
-
576
- string filename = loggingDir + "/1/" FOOBAR_LOCALHOST_PREFIX "/requests/2010/01/13/12/log.txt";
577
- struct stat buf;
578
- ensure_equals(stat(filename.c_str(), &buf), 0);
579
- string lastPos = server->getLastPos("foobar", "localhost", "requests");
580
- ensure_equals(lastPos, "2010/01/13/12/" + toString(buf.st_size));
581
- }
582
-
583
- TEST_METHOD(20) {
584
- // getLastPos() returns the empty string if log.txt or if one of
585
- // the subdirectories are missing.
586
- SystemTime::forceAll(YESTERDAY);
587
-
588
- AnalyticsLogPtr log = logger->newTransaction("foobar");
589
- log->message("hello world");
590
- log->flushToDiskAfterClose(true);
591
- log.reset();
592
-
593
- stopLoggingServer(false);
594
-
595
- string filename = loggingDir + "/1/" FOOBAR_LOCALHOST_PREFIX "/requests/2010/01/12/12/log.txt";
596
- unlink(filename.c_str());
597
-
598
- string lastPos = server->getLastPos("foobar", "localhost", "requests");
599
- ensure_equals(lastPos, "");
600
-
601
- lastPos = server->getLastPos("baz", "localhost", "requests");
602
- ensure_equals(lastPos, "");
603
- }
604
-
605
531
  TEST_METHOD(21) {
606
532
  // The server temporarily buffers data in memory.
607
533
  SystemTime::forceAll(YESTERDAY);
@@ -806,92 +732,7 @@ namespace tut {
806
732
  ensure(log->isNull());
807
733
  }
808
734
 
809
- TEST_METHOD(30) {
810
- // The "watchChanges" command causes the server to detach the
811
- // client and to pass it to the change notifier.
812
- MyChangeNotifierPtr notifier(new MyChangeNotifier(eventLoop));
813
- stopLoggingServer();
814
- startLoggingServer(boost::bind(&LoggingTest::setChangeNotifier, this, notifier));
815
-
816
- vector<string> args;
817
- MessageClient client = createConnection(false);
818
- client.write("watchChanges", NULL, NULL);
819
- ensure(client.read(args));
820
- EVENTUALLY(1,
821
- result = notifier->added == 1;
822
- );
823
- // MyChangeNotifier doesn't store the client file descriptor
824
- // so should be closed.
825
- ensure(!client.read(args));
826
- }
827
-
828
- TEST_METHOD(31) {
829
- // The server notifies the given ChangeNotifier with the
830
- // appropriate changes whenever a log file sink is flushed.
831
- MyChangeNotifierPtr notifier(new MyChangeNotifier(eventLoop));
832
- stopLoggingServer();
833
- startLoggingServer(boost::bind(&LoggingTest::setChangeNotifier, this, notifier));
834
-
835
- AnalyticsLogPtr log = logger->newTransaction("foo", "requests");
836
- log->message("hello world");
837
- log.reset();
838
-
839
- log = logger->newTransaction("bar", "requests");
840
- log->message("hello world");
841
- log.reset();
842
-
843
- SHOULD_NEVER_HAPPEN(100,
844
- lock_guard<boost::mutex> l(notifier->lock);
845
- result = !notifier->changes.empty();
846
- );
847
-
848
- MessageChannel channel(logger->getConnection());
849
- vector<string> args;
850
- channel.write("flush", NULL);
851
- ensure("(1)", channel.read(args));
852
-
853
- EVENTUALLY(1,
854
- lock_guard<boost::mutex> l(notifier->lock);
855
- result = notifier->changes.size() == 2;
856
- );
857
- unique_lock<boost::mutex> l(notifier->lock);
858
- ensure("(2)",
859
- notifier->changes.find(DataStoreId("foo", "localhost", "requests")) !=
860
- notifier->changes.end());
861
- ensure("(3)",
862
- notifier->changes.find(DataStoreId("bar", "localhost", "requests")) !=
863
- notifier->changes.end());
864
- notifier->changes.clear();
865
- l.unlock();
866
-
867
-
868
- log = logger->newTransaction("baz", "exceptions");
869
- log->message("hello world");
870
- log.reset();
871
-
872
- channel.write("flush", NULL);
873
- ensure("(4)", channel.read(args));
874
-
875
- log = logger->newTransaction("bazz", "exceptions");
876
- log->message("hello world");
877
- log.reset();
878
-
879
- EVENTUALLY(1,
880
- lock_guard<boost::mutex> l(notifier->lock);
881
- result = notifier->changes.size() == 1;
882
- );
883
- l.lock();
884
- ensure("(5)",
885
- notifier->changes.find(DataStoreId("baz", "localhost", "exceptions")) !=
886
- notifier->changes.end());
887
- l.unlock();
888
- SHOULD_NEVER_HAPPEN(100,
889
- lock_guard<boost::mutex> l(notifier->lock);
890
- result = notifier->changes.size() != 1;
891
- );
892
- }
893
-
894
- TEST_METHOD(32) {
735
+ TEST_METHOD(29) {
895
736
  // One can supply a custom node name per openTransaction command.
896
737
  MessageClient client1 = createConnection();
897
738
  vector<string> args;
@@ -910,7 +751,7 @@ namespace tut {
910
751
  ensure(fileExists(filename));
911
752
  }
912
753
 
913
- TEST_METHOD(33) {
754
+ TEST_METHOD(30) {
914
755
  // A transaction is only written to the sink if it passes all given filters.
915
756
  // Test logging of new transaction.
916
757
  SystemTime::forceAll(YESTERDAY);
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passenger
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
8
  - 0
9
- - 6
10
- version: 3.0.6
9
+ - 7
10
+ version: 3.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Phusion - http://www.phusion.nl/
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-03 00:00:00 +02:00
18
+ date: 2011-04-14 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -730,7 +730,6 @@ files:
730
730
  - ext/common/HelperAgent/BacktracesServer.h
731
731
  - ext/common/IniFile.h
732
732
  - ext/common/Logging.h
733
- - ext/common/LoggingAgent/ChangeNotifier.h
734
733
  - ext/common/LoggingAgent/DataStoreId.h
735
734
  - ext/common/LoggingAgent/FilterSupport.h
736
735
  - ext/common/LoggingAgent/LoggingServer.h
@@ -1,63 +0,0 @@
1
- /*
2
- * Phusion Passenger - http://www.modrails.com/
3
- * Copyright (c) 2010 Phusion
4
- *
5
- * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- */
25
- #ifndef _PASSENGER_CHANGE_NOTIFIER_H_
26
- #define _PASSENGER_CHANGE_NOTIFIER_H_
27
-
28
- #include <boost/function.hpp>
29
- #include <boost/shared_ptr.hpp>
30
- #include <string>
31
- #include <ev++.h>
32
- #include "DataStoreId.h"
33
- #include "../EventedClient.h"
34
- #include "../FileDescriptor.h"
35
- #include "../StaticString.h"
36
-
37
- namespace Passenger {
38
-
39
- using namespace std;
40
- using namespace boost;
41
-
42
-
43
- class ChangeNotifier {
44
- public:
45
- typedef function<string (const StaticString &groupName, const StaticString &nodeName,
46
- const StaticString &category)> GetLastPosFunction;
47
-
48
- GetLastPosFunction getLastPos;
49
-
50
- ChangeNotifier(struct ev_loop *_loop) { }
51
- virtual ~ChangeNotifier() { }
52
-
53
- virtual void addClient(const FileDescriptor &fd) { }
54
-
55
- virtual void changed(const DataStoreId &dataStoreId) { }
56
- };
57
-
58
- typedef shared_ptr<ChangeNotifier> ChangeNotifierPtr;
59
-
60
-
61
- } // namespace Passenger
62
-
63
- #endif /* _PASSENGER_CHANGE_NOTIFIER_H_ */