Mercurial > hg > truffle
annotate src/share/vm/services/diagnosticFramework.cpp @ 6024:973046802b6f
7162955: Attach api on Solaris, too many open files
Summary: Release server-side socket after client receives it.
Reviewed-by: sla, dsamersoff, dcubed, acorn
Contributed-by: dean.long@oracle.com
author | dlong |
---|---|
date | Thu, 26 Apr 2012 16:24:15 -0400 |
parents | f1cb6f9cfe21 |
children | 5a1f452f8f90 |
rev | line source |
---|---|
4133 | 1 /* |
4932
f1cb6f9cfe21
7145243: Need additional specializations for argument parsing framework
fparain
parents:
4773
diff
changeset
|
2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. |
4133 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 #include "precompiled.hpp" | |
26 #include "memory/oopFactory.hpp" | |
27 #include "runtime/javaCalls.hpp" | |
28 #include "runtime/mutexLocker.hpp" | |
29 #include "services/diagnosticArgument.hpp" | |
30 #include "services/diagnosticFramework.hpp" | |
31 #include "services/management.hpp" | |
32 | |
33 CmdLine::CmdLine(const char* line, size_t len, bool no_command_name) { | |
34 assert(line != NULL, "Command line string should not be NULL"); | |
35 const char* line_end; | |
36 const char* cmd_end; | |
37 | |
38 _cmd = line; | |
39 line_end = &line[len]; | |
40 | |
41 // Skip whitespace in the beginning of the line. | |
42 while (_cmd < line_end && isspace((int) _cmd[0])) { | |
43 _cmd++; | |
44 } | |
45 cmd_end = _cmd; | |
46 | |
47 if (no_command_name) { | |
48 _cmd = NULL; | |
49 _cmd_len = 0; | |
50 } else { | |
51 // Look for end of the command name | |
52 while (cmd_end < line_end && !isspace((int) cmd_end[0])) { | |
53 cmd_end++; | |
54 } | |
55 _cmd_len = cmd_end - _cmd; | |
56 } | |
57 _args = cmd_end; | |
58 _args_len = line_end - _args; | |
59 } | |
60 | |
61 bool DCmdArgIter::next(TRAPS) { | |
62 if (_len == 0) return false; | |
63 // skipping spaces | |
4932
f1cb6f9cfe21
7145243: Need additional specializations for argument parsing framework
fparain
parents:
4773
diff
changeset
|
64 while (_cursor < _len - 1 && _buffer[_cursor] == _delim) { |
4133 | 65 _cursor++; |
66 } | |
67 // handling end of command line | |
68 if (_cursor >= _len - 1) { | |
69 _cursor = _len - 1; | |
70 _key_addr = &_buffer[_len - 1]; | |
71 _key_len = 0; | |
72 _value_addr = &_buffer[_len - 1]; | |
73 _value_len = 0; | |
74 return false; | |
75 } | |
76 // extracting first item, argument or option name | |
77 _key_addr = &_buffer[_cursor]; | |
78 while (_cursor <= _len - 1 && _buffer[_cursor] != '=' && _buffer[_cursor] != _delim) { | |
79 // argument can be surrounded by single or double quotes | |
80 if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') { | |
81 _key_addr++; | |
82 char quote = _buffer[_cursor]; | |
83 while (_cursor < _len - 1) { | |
84 _cursor++; | |
85 if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') { | |
86 break; | |
87 } | |
88 } | |
89 if (_buffer[_cursor] != quote) { | |
90 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), | |
91 "Format error in diagnostic command arguments", false); | |
92 } | |
93 break; | |
94 } | |
95 _cursor++; | |
96 } | |
97 _key_len = &_buffer[_cursor] - _key_addr; | |
98 // check if the argument has the <key>=<value> format | |
99 if (_cursor <= _len -1 && _buffer[_cursor] == '=') { | |
100 _cursor++; | |
101 _value_addr = &_buffer[_cursor]; | |
102 // extract the value | |
103 while (_cursor <= _len - 1 && _buffer[_cursor] != _delim) { | |
104 // value can be surrounded by simple or double quotes | |
105 if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') { | |
106 _value_addr++; | |
107 char quote = _buffer[_cursor]; | |
108 while (_cursor < _len - 1) { | |
109 _cursor++; | |
110 if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') { | |
111 break; | |
112 } | |
113 } | |
114 if (_buffer[_cursor] != quote) { | |
115 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), | |
116 "Format error in diagnostic command arguments", false); | |
117 } | |
118 break; | |
119 } | |
120 _cursor++; | |
121 } | |
122 _value_len = &_buffer[_cursor] - _value_addr; | |
123 } else { | |
124 _value_addr = NULL; | |
125 _value_len = 0; | |
126 } | |
127 return _key_len != 0; | |
128 } | |
129 | |
130 bool DCmdInfo::by_name(void* cmd_name, DCmdInfo* info) { | |
131 if (info == NULL) return false; | |
132 return strcmp((const char*)cmd_name, info->name()) == 0; | |
133 } | |
134 | |
135 void DCmdParser::add_dcmd_option(GenDCmdArgument* arg) { | |
136 assert(arg != NULL, "Sanity"); | |
137 if (_options == NULL) { | |
138 _options = arg; | |
139 } else { | |
140 GenDCmdArgument* o = _options; | |
141 while (o->next() != NULL) { | |
142 o = o->next(); | |
143 } | |
144 o->set_next(arg); | |
145 } | |
146 arg->set_next(NULL); | |
147 Thread* THREAD = Thread::current(); | |
148 arg->init_value(THREAD); | |
149 if (HAS_PENDING_EXCEPTION) { | |
150 fatal("Initialization must be successful"); | |
151 } | |
152 } | |
153 | |
154 void DCmdParser::add_dcmd_argument(GenDCmdArgument* arg) { | |
155 assert(arg != NULL, "Sanity"); | |
156 if (_arguments_list == NULL) { | |
157 _arguments_list = arg; | |
158 } else { | |
159 GenDCmdArgument* a = _arguments_list; | |
160 while (a->next() != NULL) { | |
161 a = a->next(); | |
162 } | |
163 a->set_next(arg); | |
164 } | |
165 arg->set_next(NULL); | |
166 Thread* THREAD = Thread::current(); | |
167 arg->init_value(THREAD); | |
168 if (HAS_PENDING_EXCEPTION) { | |
169 fatal("Initialization must be successful"); | |
170 } | |
171 } | |
172 | |
173 void DCmdParser::parse(CmdLine* line, char delim, TRAPS) { | |
174 GenDCmdArgument* next_argument = _arguments_list; | |
175 DCmdArgIter iter(line->args_addr(), line->args_len(), delim); | |
176 bool cont = iter.next(CHECK); | |
177 while (cont) { | |
178 GenDCmdArgument* arg = lookup_dcmd_option(iter.key_addr(), | |
179 iter.key_length()); | |
180 if (arg != NULL) { | |
181 arg->read_value(iter.value_addr(), iter.value_length(), CHECK); | |
182 } else { | |
183 if (next_argument != NULL) { | |
184 arg = next_argument; | |
185 arg->read_value(iter.key_addr(), iter.key_length(), CHECK); | |
186 next_argument = next_argument->next(); | |
187 } else { | |
188 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
189 "Unknown argument in diagnostic command"); | |
190 } | |
191 } | |
192 cont = iter.next(CHECK); | |
193 } | |
194 check(CHECK); | |
195 } | |
196 | |
197 GenDCmdArgument* DCmdParser::lookup_dcmd_option(const char* name, size_t len) { | |
198 GenDCmdArgument* arg = _options; | |
199 while (arg != NULL) { | |
200 if (strlen(arg->name()) == len && | |
201 strncmp(name, arg->name(), len) == 0) { | |
202 return arg; | |
203 } | |
204 arg = arg->next(); | |
205 } | |
206 return NULL; | |
207 } | |
208 | |
209 void DCmdParser::check(TRAPS) { | |
210 GenDCmdArgument* arg = _arguments_list; | |
211 while (arg != NULL) { | |
212 if (arg->is_mandatory() && !arg->has_value()) { | |
213 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
214 "Missing argument for diagnostic command"); | |
215 } | |
216 arg = arg->next(); | |
217 } | |
218 arg = _options; | |
219 while (arg != NULL) { | |
220 if (arg->is_mandatory() && !arg->has_value()) { | |
221 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
222 "Missing option for diagnostic command"); | |
223 } | |
224 arg = arg->next(); | |
225 } | |
226 } | |
227 | |
228 void DCmdParser::print_help(outputStream* out, const char* cmd_name) { | |
4773 | 229 out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]"); |
4133 | 230 GenDCmdArgument* arg = _arguments_list; |
231 while (arg != NULL) { | |
232 if (arg->is_mandatory()) { | |
233 out->print(" <%s>", arg->name()); | |
234 } else { | |
235 out->print(" [<%s>]", arg->name()); | |
236 } | |
237 arg = arg->next(); | |
238 } | |
239 out->print_cr(""); | |
240 if (_arguments_list != NULL) { | |
241 out->print_cr("\nArguments:"); | |
242 arg = _arguments_list; | |
243 while (arg != NULL) { | |
244 out->print("\t%s : %s %s (%s, ", arg->name(), | |
245 arg->is_mandatory() ? "" : "[optional]", | |
246 arg->description(), arg->type()); | |
247 if (arg->has_default()) { | |
248 out->print(arg->default_string()); | |
249 } else { | |
250 out->print("no default value"); | |
251 } | |
252 out->print_cr(")"); | |
253 arg = arg->next(); | |
254 } | |
255 } | |
256 if (_options != NULL) { | |
257 out->print_cr("\nOptions: (options must be specified using the <key> or <key>=<value> syntax)"); | |
258 arg = _options; | |
259 while (arg != NULL) { | |
260 out->print("\t%s : %s %s (%s, ", arg->name(), | |
261 arg->is_mandatory() ? "" : "[optional]", | |
262 arg->description(), arg->type()); | |
263 if (arg->has_default()) { | |
264 out->print(arg->default_string()); | |
265 } else { | |
266 out->print("no default value"); | |
267 } | |
268 out->print_cr(")"); | |
269 arg = arg->next(); | |
270 } | |
271 } | |
272 } | |
273 | |
274 void DCmdParser::reset(TRAPS) { | |
275 GenDCmdArgument* arg = _arguments_list; | |
276 while (arg != NULL) { | |
277 arg->reset(CHECK); | |
278 arg = arg->next(); | |
279 } | |
280 arg = _options; | |
281 while (arg != NULL) { | |
282 arg->reset(CHECK); | |
283 arg = arg->next(); | |
284 } | |
285 } | |
286 | |
287 void DCmdParser::cleanup() { | |
288 GenDCmdArgument* arg = _arguments_list; | |
289 while (arg != NULL) { | |
290 arg->cleanup(); | |
291 arg = arg->next(); | |
292 } | |
293 arg = _options; | |
294 while (arg != NULL) { | |
295 arg->cleanup(); | |
296 arg = arg->next(); | |
297 } | |
298 } | |
299 | |
300 int DCmdParser::num_arguments() { | |
301 GenDCmdArgument* arg = _arguments_list; | |
302 int count = 0; | |
303 while (arg != NULL) { | |
304 count++; | |
305 arg = arg->next(); | |
306 } | |
307 arg = _options; | |
308 while (arg != NULL) { | |
309 count++; | |
310 arg = arg->next(); | |
311 } | |
312 return count; | |
313 } | |
314 | |
315 GrowableArray<const char *>* DCmdParser::argument_name_array() { | |
316 int count = num_arguments(); | |
317 GrowableArray<const char *>* array = new GrowableArray<const char *>(count); | |
318 GenDCmdArgument* arg = _arguments_list; | |
319 while (arg != NULL) { | |
320 array->append(arg->name()); | |
321 arg = arg->next(); | |
322 } | |
323 arg = _options; | |
324 while (arg != NULL) { | |
325 array->append(arg->name()); | |
326 arg = arg->next(); | |
327 } | |
328 return array; | |
329 } | |
330 | |
331 GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() { | |
332 int count = num_arguments(); | |
333 GrowableArray<DCmdArgumentInfo*>* array = new GrowableArray<DCmdArgumentInfo *>(count); | |
334 int idx = 0; | |
335 GenDCmdArgument* arg = _arguments_list; | |
336 while (arg != NULL) { | |
337 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), | |
338 arg->type(), arg->default_string(), arg->is_mandatory(), | |
339 false, idx)); | |
340 idx++; | |
341 arg = arg->next(); | |
342 } | |
343 arg = _options; | |
344 while (arg != NULL) { | |
345 array->append(new DCmdArgumentInfo(arg->name(), arg->description(), | |
346 arg->type(), arg->default_string(), arg->is_mandatory(), | |
347 true)); | |
348 arg = arg->next(); | |
349 } | |
350 return array; | |
351 } | |
352 | |
353 DCmdFactory* DCmdFactory::_DCmdFactoryList = NULL; | |
354 | |
355 void DCmd::parse_and_execute(outputStream* out, const char* cmdline, | |
356 char delim, TRAPS) { | |
357 | |
358 if (cmdline == NULL) return; // Nothing to do! | |
359 DCmdIter iter(cmdline, '\n'); | |
360 | |
361 while (iter.has_next()) { | |
362 CmdLine line = iter.next(); | |
363 if (line.is_stop()) { | |
364 break; | |
365 } | |
366 if (line.is_executable()) { | |
367 DCmd* command = DCmdFactory::create_local_DCmd(line, out, CHECK); | |
368 assert(command != NULL, "command error must be handled before this line"); | |
369 DCmdMark mark(command); | |
370 command->parse(&line, delim, CHECK); | |
371 command->execute(CHECK); | |
372 } | |
373 } | |
374 } | |
375 | |
4773 | 376 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) { |
377 _dcmdparser.parse(line, delim, CHECK); | |
378 } | |
379 | |
380 void DCmdWithParser::print_help(const char* name) { | |
381 _dcmdparser.print_help(output(), name); | |
382 } | |
383 | |
384 void DCmdWithParser::reset(TRAPS) { | |
385 _dcmdparser.reset(CHECK); | |
386 } | |
387 | |
388 void DCmdWithParser::cleanup() { | |
389 _dcmdparser.cleanup(); | |
390 } | |
391 | |
392 GrowableArray<const char*>* DCmdWithParser::argument_name_array() { | |
393 return _dcmdparser.argument_name_array(); | |
394 } | |
395 | |
396 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() { | |
397 return _dcmdparser.argument_info_array(); | |
398 } | |
399 | |
4133 | 400 Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true); |
401 | |
402 DCmdFactory* DCmdFactory::factory(const char* name, size_t len) { | |
403 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); | |
404 DCmdFactory* factory = _DCmdFactoryList; | |
405 while (factory != NULL) { | |
406 if (strlen(factory->name()) == len && | |
407 strncmp(name, factory->name(), len) == 0) { | |
408 return factory; | |
409 } | |
410 factory = factory->_next; | |
411 } | |
412 return NULL; | |
413 } | |
414 | |
415 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) { | |
416 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); | |
417 factory->_next = _DCmdFactoryList; | |
418 _DCmdFactoryList = factory; | |
419 return 0; // Actually, there's no checks for duplicates | |
420 } | |
421 | |
422 DCmd* DCmdFactory::create_global_DCmd(CmdLine &line, outputStream* out, TRAPS) { | |
423 DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); | |
424 if (f != NULL) { | |
425 if (f->is_enabled()) { | |
426 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), | |
427 f->disabled_message()); | |
428 } | |
429 return f->create_Cheap_instance(out); | |
430 } | |
431 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), | |
432 "Unknown diagnostic command"); | |
433 } | |
434 | |
435 DCmd* DCmdFactory::create_local_DCmd(CmdLine &line, outputStream* out, TRAPS) { | |
436 DCmdFactory* f = factory(line.cmd_addr(), line.cmd_len()); | |
437 if (f != NULL) { | |
438 if (!f->is_enabled()) { | |
439 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), | |
440 f->disabled_message()); | |
441 } | |
442 return f->create_resource_instance(out); | |
443 } | |
444 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), | |
445 "Unknown diagnostic command"); | |
446 } | |
447 | |
448 GrowableArray<const char*>* DCmdFactory::DCmd_list() { | |
449 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); | |
450 GrowableArray<const char*>* array = new GrowableArray<const char*>(); | |
451 DCmdFactory* factory = _DCmdFactoryList; | |
452 while (factory != NULL) { | |
453 if (!factory->is_hidden()) { | |
454 array->append(factory->name()); | |
455 } | |
456 factory = factory->next(); | |
457 } | |
458 return array; | |
459 } | |
460 | |
461 GrowableArray<DCmdInfo*>* DCmdFactory::DCmdInfo_list() { | |
462 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag); | |
463 GrowableArray<DCmdInfo*>* array = new GrowableArray<DCmdInfo*>(); | |
464 DCmdFactory* factory = _DCmdFactoryList; | |
465 while (factory != NULL) { | |
466 if (!factory->is_hidden()) { | |
467 array->append(new DCmdInfo(factory->name(), | |
468 factory->description(), factory->impact(), | |
469 factory->num_arguments(), factory->is_enabled())); | |
470 } | |
471 factory = factory->next(); | |
472 } | |
473 return array; | |
474 } |