We got nominated! Help us out and vote for GitHub as Best Bootstrapped Startup of 2008. (You can vote once a day.) [ hide ]

public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
Add ability to output pool information in XML so that CLI admin tools can 
better parse the information.
Hongli Lai (Phusion) (author)
Thu Nov 20 08:49:44 -0800 2008
commit  008e01ff9e03cbd2d46d04c75e5b1d14d10bb2e3
tree    3d40661e81a98ca1a5ea38f29cec87cc0bfdfb6e
parent  f50d427a7e408065d47f2829b78c99bb2994ef11
...
19
20
21
 
22
23
24
...
64
65
66
67
 
68
69
70
71
72
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
75
76
...
19
20
21
22
23
24
25
...
65
66
67
 
68
69
 
 
 
 
 
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
0
@@ -19,6 +19,7 @@
0
 
0
 $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
0
 $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../ext")
0
+require 'passenger/message_channel'
0
 
0
 # ANSI color codes
0
 RESET = "\e[0m"
0
@@ -64,13 +65,23 @@ def process_is_alive?(pid)
0
   end
0
 end
0
 
0
-def show_status(status_fifo)
0
+def show_status(status_fifo, format = :text)
0
   begin
0
- text = File.read(status_fifo.filename)
0
- # Colorize output
0
- text.gsub!(/^(----)(.*)$/, YELLOW + BLUE_BG + BOLD + '\1\2' + RESET)
0
- text.gsub!(/^( +in '.*? )(.*?)\(/, '\1' + BOLD + '\2' + RESET + '(')
0
- puts text
0
+ text = nil
0
+ xml = nil
0
+ File.open(status_fifo.filename, 'r') do |f|
0
+ channel = Passenger::MessageChannel.new(f)
0
+ text = channel.read_scalar
0
+ xml = channel.read_scalar
0
+ end
0
+ if format == :text
0
+ # Colorize output
0
+ text.gsub!(/^(----)(.*)$/, YELLOW + BLUE_BG + BOLD + '\1\2' + RESET)
0
+ text.gsub!(/^( +in '.*? )(.*?)\(/, '\1' + BOLD + '\2' + RESET + '(')
0
+ puts text
0
+ else
0
+ puts xml
0
+ end
0
   rescue => e
0
     STDERR.puts "*** ERROR: Cannot query status for Passenger instance #{status_fifo.pid}:"
0
     STDERR.puts e.to_s
...
110
111
112
 
113
114
115
116
117
118
119
120
121
122
123
124
 
 
 
 
 
 
 
125
126
127
...
110
111
112
113
114
115
116
117
118
119
 
 
 
 
120
 
121
122
123
124
125
126
127
128
129
130
0
@@ -110,18 +110,21 @@ private:
0
         }
0
         
0
         UPDATE_TRACE_POINT();
0
+ MessageChannel channel(fileno(f));
0
         string report;
0
         report.append("----------- Backtraces -----------\n");
0
         report.append(oxt::thread::all_backtraces());
0
         report.append("\n\n");
0
         report.append(pool.toString());
0
         
0
- fwrite(report.c_str(), 1, report.size(), f);
0
- syscalls::fclose(f);
0
-
0
- // Prevent sending too much data at once.
0
         UPDATE_TRACE_POINT();
0
- sleep(1);
0
+ try {
0
+ channel.writeScalar(report);
0
+ channel.writeScalar(pool.toXml());
0
+ } catch (...) {
0
+ // Ignore write errors.
0
+ }
0
+ syscalls::fclose(f);
0
       }
0
     } catch (const boost::thread_interrupted &) {
0
       P_TRACE(2, "Status report thread interrupted.");
...
685
686
687
 
 
 
 
 
 
 
 
 
688
689
690
...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
0
@@ -685,6 +685,15 @@ public:
0
     const char *ruby, *user;
0
     string applicationPoolServerExe, spawnServer;
0
     
0
+ /*
0
+ * As described in the comment in init_module, upon (re)starting
0
+ * Apache, the Hooks constructor is called twice. We unset
0
+ * PHUSION_PASSENGER_TMP before calling createPassengerTmpDir()
0
+ * because we want the temp directory's name to contain the PID
0
+ * of the process in which the Hooks constructor was called for
0
+ * the second time.
0
+ */
0
+ unsetenv("PHUSION_PASSENGER_TMP");
0
     createPassengerTempDir();
0
     
0
     ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
...
766
767
768
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
770
771
...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
0
@@ -766,6 +766,48 @@ public:
0
       return toString(boost::defer_lock);
0
     }
0
   }
0
+
0
+ /**
0
+ * Returns an XML description of the internal state of the
0
+ * application pool.
0
+ */
0
+ virtual string toXml() const {
0
+ unique_lock<boost::mutex> l(lock);
0
+ stringstream result;
0
+ DomainMap::const_iterator it;
0
+
0
+ result << "<?xml version=\"1.0\" encoding=\"iso8859-1\" ?>\n";
0
+ result << "<info>";
0
+
0
+ result << "<domains>";
0
+ for (it = domains.begin(); it != domains.end(); it++) {
0
+ Domain *domain = it->second.get();
0
+ AppContainerList *instances = &domain->instances;
0
+ AppContainerList::const_iterator lit;
0
+
0
+ result << "<domain>";
0
+ result << "<name>" << escapeForXml(it->first) << "</name>";
0
+
0
+ result << "<instances>";
0
+ for (lit = instances->begin(); lit != instances->end(); lit++) {
0
+ AppContainer *container = lit->get();
0
+
0
+ result << "<instance>";
0
+ result << "<pid>" << container->app->getPid() << "</pid>";
0
+ result << "<sessions>" << container->sessions << "</sessions>";
0
+ result << "<processed>" << container->processed << "</processed>";
0
+ result << "<uptime>" << container->uptime() << "</uptime>";
0
+ result << "</instance>";
0
+ }
0
+ result << "</instances>";
0
+
0
+ result << "</domain>";
0
+ }
0
+ result << "</domains>";
0
+
0
+ result << "</info>";
0
+ return result.str();
0
+ }
0
 };
0
 
0
 } // namespace Passenger
...
171
172
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
175
176
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
0
@@ -171,6 +171,45 @@ canonicalizePath(const string &path) {
0
   #endif
0
 }
0
 
0
+string
0
+escapeForXml(const string &input) {
0
+ string result(input);
0
+ string::size_type input_pos = 0;
0
+ string::size_type input_end_pos = input.size();
0
+ string::size_type result_pos = 0;
0
+
0
+ while (input_pos < input_end_pos) {
0
+ const unsigned char ch = input[input_pos];
0
+
0
+ if ((ch >= 'A' && ch <= 'z')
0
+ || (ch >= '0' && ch <= '9')
0
+ || ch == '/' || ch == ' ' || ch == '_' || ch == '.') {
0
+ // This is an ASCII character. Ignore it and
0
+ // go to next character.
0
+ result_pos++;
0
+ } else {
0
+ // Not an ASCII character; escape it.
0
+ char escapedCharacter[sizeof("&#255;") + 1];
0
+ int size;
0
+
0
+ size = snprintf(escapedCharacter,
0
+ sizeof(escapedCharacter) - 1,
0
+ "&#%d;",
0
+ (int) ch);
0
+ if (size < 0) {
0
+ throw std::bad_alloc();
0
+ }
0
+ escapedCharacter[sizeof(escapedCharacter) - 1] = '\0';
0
+
0
+ result.replace(result_pos, 1, escapedCharacter, size);
0
+ result_pos += size;
0
+ }
0
+ input_pos++;
0
+ }
0
+
0
+ return result;
0
+}
0
+
0
 const char *
0
 getTempDir() {
0
   const char *temp_dir = getenv("TMP");
...
203
204
205
 
 
 
 
 
 
 
 
206
207
208
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
0
@@ -203,6 +203,14 @@ string findApplicationPoolServer(const char *passengerRoot);
0
 string canonicalizePath(const string &path);
0
 
0
 /**
0
+ * Escape the given raw string into an XML value.
0
+ *
0
+ * @throws std::bad_alloc Something went wrong.
0
+ * @ingroup Support
0
+ */
0
+string escapeForXml(const string &input);
0
+
0
+/**
0
  * Return the path name for the directory in which temporary files are
0
  * to be stored.
0
  *
...
223
224
225
 
 
 
 
 
 
 
 
 
 
 
 
226
...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
0
@@ -223,4 +223,16 @@ namespace tut {
0
     removeDirTree("utils_test.tmp");
0
     ensure_equals(size, 0u);
0
   }
0
+
0
+ /***** Test escapeForXml() *****/
0
+
0
+ TEST_METHOD(25) {
0
+ ensure_equals(escapeForXml(""), "");
0
+ ensure_equals(escapeForXml("hello world"), "hello world");
0
+ ensure_equals(escapeForXml("./hello_world/foo.txt"), "./hello_world/foo.txt");
0
+ ensure_equals(escapeForXml("hello<world"), "hello&#60;world");
0
+ ensure_equals(escapeForXml("hello\xFFworld"), "hello&#255;world");
0
+ ensure_equals(escapeForXml("hello\xFF\xCCworld"), "hello&#255;&#204;world");
0
+ ensure_equals(escapeForXml("hello\xFFworld\xCC"), "hello&#255;world&#204;");
0
+ }
0
 }

Comments

    No one has commented yet.