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 "jvm.h"
27 #include "memory/oopFactory.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/handles.inline.hpp"
31 #include "runtime/javaCalls.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "services/diagnosticArgument.hpp"
34 #include "services/diagnosticFramework.hpp"
35 #include "services/management.hpp"
36
37 CmdLine::CmdLine(const char* line, size_t len, bool no_command_name) {
38 assert(line != NULL, "Command line string should not be NULL");
39 const char* line_end;
40 const char* cmd_end;
41
42 _cmd = line;
43 line_end = &line[len];
44
45 // Skip whitespace in the beginning of the line.
46 while (_cmd < line_end && isspace((int) _cmd[0])) {
47 _cmd++;
48 }
49 cmd_end = _cmd;
50
51 if (no_command_name) {
52 _cmd = NULL;
53 _cmd_len = 0;
54 } else {
55 // Look for end of the command name
56 while (cmd_end < line_end && !isspace((int) cmd_end[0])) {
57 cmd_end++;
234 const size_t buflen = 256;
235 char buf[buflen];
236 GenDCmdArgument* arg = _arguments_list;
237 while (arg != NULL) {
238 if (arg->is_mandatory() && !arg->has_value()) {
239 jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
240 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
241 }
242 arg = arg->next();
243 }
244 arg = _options;
245 while (arg != NULL) {
246 if (arg->is_mandatory() && !arg->has_value()) {
247 jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
248 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
249 }
250 arg = arg->next();
251 }
252 }
253
254 void DCmdParser::print_help(outputStream* out, const char* cmd_name) {
255 out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
256 GenDCmdArgument* arg = _arguments_list;
257 while (arg != NULL) {
258 if (arg->is_mandatory()) {
259 out->print(" <%s>", arg->name());
260 } else {
261 out->print(" [<%s>]", arg->name());
262 }
263 arg = arg->next();
264 }
265 out->cr();
266 if (_arguments_list != NULL) {
267 out->print_cr("\nArguments:");
268 arg = _arguments_list;
269 while (arg != NULL) {
270 out->print("\t%s : %s %s (%s, ", arg->name(),
271 arg->is_mandatory() ? "" : "[optional]",
272 arg->description(), arg->type());
273 if (arg->has_default()) {
274 out->print("%s", arg->default_string());
306 arg = _options;
307 while (arg != NULL) {
308 arg->reset(CHECK);
309 arg = arg->next();
310 }
311 }
312
313 void DCmdParser::cleanup() {
314 GenDCmdArgument* arg = _arguments_list;
315 while (arg != NULL) {
316 arg->cleanup();
317 arg = arg->next();
318 }
319 arg = _options;
320 while (arg != NULL) {
321 arg->cleanup();
322 arg = arg->next();
323 }
324 }
325
326 int DCmdParser::num_arguments() {
327 GenDCmdArgument* arg = _arguments_list;
328 int count = 0;
329 while (arg != NULL) {
330 count++;
331 arg = arg->next();
332 }
333 arg = _options;
334 while (arg != NULL) {
335 count++;
336 arg = arg->next();
337 }
338 return count;
339 }
340
341 GrowableArray<const char *>* DCmdParser::argument_name_array() {
342 int count = num_arguments();
343 GrowableArray<const char *>* array = new GrowableArray<const char *>(count);
344 GenDCmdArgument* arg = _arguments_list;
345 while (arg != NULL) {
346 array->append(arg->name());
347 arg = arg->next();
348 }
349 arg = _options;
350 while (arg != NULL) {
351 array->append(arg->name());
352 arg = arg->next();
353 }
354 return array;
355 }
356
357 GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() {
358 int count = num_arguments();
359 GrowableArray<DCmdArgumentInfo*>* array = new GrowableArray<DCmdArgumentInfo *>(count);
360 int idx = 0;
361 GenDCmdArgument* arg = _arguments_list;
362 while (arg != NULL) {
363 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
364 arg->type(), arg->default_string(), arg->is_mandatory(),
365 false, arg->allow_multiple(), idx));
366 idx++;
367 arg = arg->next();
368 }
369 arg = _options;
370 while (arg != NULL) {
371 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
372 arg->type(), arg->default_string(), arg->is_mandatory(),
373 true, arg->allow_multiple()));
374 arg = arg->next();
375 }
376 return array;
377 }
382 void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
383 const char* cmdline, char delim, TRAPS) {
384
385 if (cmdline == NULL) return; // Nothing to do!
386 DCmdIter iter(cmdline, '\n');
387
388 int count = 0;
389 while (iter.has_next()) {
390 if(source == DCmd_Source_MBean && count > 0) {
391 // When diagnostic commands are invoked via JMX, each command line
392 // must contains one and only one command because of the Permission
393 // checks performed by the DiagnosticCommandMBean
394 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
395 "Invalid syntax");
396 }
397 CmdLine line = iter.next();
398 if (line.is_stop()) {
399 break;
400 }
401 if (line.is_executable()) {
402 DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
403 assert(command != NULL, "command error must be handled before this line");
404 DCmdMark mark(command);
405 command->parse(&line, delim, CHECK);
406 command->execute(source, CHECK);
407 }
408 count++;
409 }
410 }
411
412 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
413 _dcmdparser.parse(line, delim, CHECK);
414 }
415
416 void DCmdWithParser::print_help(const char* name) {
417 _dcmdparser.print_help(output(), name);
418 }
419
420 void DCmdWithParser::reset(TRAPS) {
421 _dcmdparser.reset(CHECK);
422 }
423
424 void DCmdWithParser::cleanup() {
425 _dcmdparser.cleanup();
426 }
427
428 GrowableArray<const char*>* DCmdWithParser::argument_name_array() {
429 return _dcmdparser.argument_name_array();
430 }
431
432 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
433 return _dcmdparser.argument_info_array();
434 }
435
436 void DCmdFactory::push_jmx_notification_request() {
437 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
438 _has_pending_jmx_notification = true;
439 Service_lock->notify_all();
440 }
441
442 void DCmdFactory::send_notification(TRAPS) {
443 DCmdFactory::send_notification_internal(THREAD);
444 // Clearing pending exception to avoid premature termination of
445 // the service thread
446 if (HAS_PENDING_EXCEPTION) {
447 CLEAR_PENDING_EXCEPTION;
448 }
449 }
450 void DCmdFactory::send_notification_internal(TRAPS) {
451 ResourceMark rm(THREAD);
452 HandleMark hm(THREAD);
500 if(factory->export_flags() & source) {
501 return factory;
502 } else {
503 return NULL;
504 }
505 }
506 factory = factory->_next;
507 }
508 return NULL;
509 }
510
511 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
512 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
513 factory->_next = _DCmdFactoryList;
514 _DCmdFactoryList = factory;
515 if (_send_jmx_notification && !factory->_hidden
516 && (factory->_export_flags & DCmd_Source_MBean)) {
517 DCmdFactory::push_jmx_notification_request();
518 }
519 return 0; // Actually, there's no checks for duplicates
520 }
521
522 DCmd* DCmdFactory::create_global_DCmd(DCmdSource source, CmdLine &line,
523 outputStream* out, TRAPS) {
524 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
525 if (f != NULL) {
526 if (f->is_enabled()) {
527 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
528 f->disabled_message());
529 }
530 return f->create_Cheap_instance(out);
531 }
532 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
533 "Unknown diagnostic command");
534 }
535
536 DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
537 outputStream* out, TRAPS) {
538 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
539 if (f != NULL) {
540 if (!f->is_enabled()) {
541 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
542 f->disabled_message());
543 }
544 return f->create_resource_instance(out);
545 }
546 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
547 "Unknown diagnostic command");
548 }
549
550 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
551 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
552 GrowableArray<const char*>* array = new GrowableArray<const char*>();
553 DCmdFactory* factory = _DCmdFactoryList;
|
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 "jvm.h"
27 #include "memory/oopFactory.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/handles.inline.hpp"
31 #include "runtime/javaCalls.hpp"
32 #include "runtime/mutexLocker.hpp"
33 #include "services/diagnosticArgument.hpp"
34 #include "services/diagnosticFramework.hpp"
35 #include "services/management.hpp"
36
37 CmdLine::CmdLine(const char* line, size_t len, bool no_command_name)
38 : _cmd(line), _cmd_len(0), _args(NULL), _args_len(0)
39 {
40 assert(line != NULL, "Command line string should not be NULL");
41 const char* line_end;
42 const char* cmd_end;
43
44 _cmd = line;
45 line_end = &line[len];
46
47 // Skip whitespace in the beginning of the line.
48 while (_cmd < line_end && isspace((int) _cmd[0])) {
49 _cmd++;
50 }
51 cmd_end = _cmd;
52
53 if (no_command_name) {
54 _cmd = NULL;
55 _cmd_len = 0;
56 } else {
57 // Look for end of the command name
58 while (cmd_end < line_end && !isspace((int) cmd_end[0])) {
59 cmd_end++;
236 const size_t buflen = 256;
237 char buf[buflen];
238 GenDCmdArgument* arg = _arguments_list;
239 while (arg != NULL) {
240 if (arg->is_mandatory() && !arg->has_value()) {
241 jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
242 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
243 }
244 arg = arg->next();
245 }
246 arg = _options;
247 while (arg != NULL) {
248 if (arg->is_mandatory() && !arg->has_value()) {
249 jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
250 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
251 }
252 arg = arg->next();
253 }
254 }
255
256 void DCmdParser::print_help(outputStream* out, const char* cmd_name) const {
257 out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
258 GenDCmdArgument* arg = _arguments_list;
259 while (arg != NULL) {
260 if (arg->is_mandatory()) {
261 out->print(" <%s>", arg->name());
262 } else {
263 out->print(" [<%s>]", arg->name());
264 }
265 arg = arg->next();
266 }
267 out->cr();
268 if (_arguments_list != NULL) {
269 out->print_cr("\nArguments:");
270 arg = _arguments_list;
271 while (arg != NULL) {
272 out->print("\t%s : %s %s (%s, ", arg->name(),
273 arg->is_mandatory() ? "" : "[optional]",
274 arg->description(), arg->type());
275 if (arg->has_default()) {
276 out->print("%s", arg->default_string());
308 arg = _options;
309 while (arg != NULL) {
310 arg->reset(CHECK);
311 arg = arg->next();
312 }
313 }
314
315 void DCmdParser::cleanup() {
316 GenDCmdArgument* arg = _arguments_list;
317 while (arg != NULL) {
318 arg->cleanup();
319 arg = arg->next();
320 }
321 arg = _options;
322 while (arg != NULL) {
323 arg->cleanup();
324 arg = arg->next();
325 }
326 }
327
328 int DCmdParser::num_arguments() const {
329 GenDCmdArgument* arg = _arguments_list;
330 int count = 0;
331 while (arg != NULL) {
332 count++;
333 arg = arg->next();
334 }
335 arg = _options;
336 while (arg != NULL) {
337 count++;
338 arg = arg->next();
339 }
340 return count;
341 }
342
343 GrowableArray<const char *>* DCmdParser::argument_name_array() const {
344 int count = num_arguments();
345 GrowableArray<const char *>* array = new GrowableArray<const char *>(count);
346 GenDCmdArgument* arg = _arguments_list;
347 while (arg != NULL) {
348 array->append(arg->name());
349 arg = arg->next();
350 }
351 arg = _options;
352 while (arg != NULL) {
353 array->append(arg->name());
354 arg = arg->next();
355 }
356 return array;
357 }
358
359 GrowableArray<DCmdArgumentInfo*>* DCmdParser::argument_info_array() const {
360 int count = num_arguments();
361 GrowableArray<DCmdArgumentInfo*>* array = new GrowableArray<DCmdArgumentInfo *>(count);
362 int idx = 0;
363 GenDCmdArgument* arg = _arguments_list;
364 while (arg != NULL) {
365 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
366 arg->type(), arg->default_string(), arg->is_mandatory(),
367 false, arg->allow_multiple(), idx));
368 idx++;
369 arg = arg->next();
370 }
371 arg = _options;
372 while (arg != NULL) {
373 array->append(new DCmdArgumentInfo(arg->name(), arg->description(),
374 arg->type(), arg->default_string(), arg->is_mandatory(),
375 true, arg->allow_multiple()));
376 arg = arg->next();
377 }
378 return array;
379 }
384 void DCmd::parse_and_execute(DCmdSource source, outputStream* out,
385 const char* cmdline, char delim, TRAPS) {
386
387 if (cmdline == NULL) return; // Nothing to do!
388 DCmdIter iter(cmdline, '\n');
389
390 int count = 0;
391 while (iter.has_next()) {
392 if(source == DCmd_Source_MBean && count > 0) {
393 // When diagnostic commands are invoked via JMX, each command line
394 // must contains one and only one command because of the Permission
395 // checks performed by the DiagnosticCommandMBean
396 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
397 "Invalid syntax");
398 }
399 CmdLine line = iter.next();
400 if (line.is_stop()) {
401 break;
402 }
403 if (line.is_executable()) {
404 ResourceMark rm;
405 DCmd* command = DCmdFactory::create_local_DCmd(source, line, out, CHECK);
406 assert(command != NULL, "command error must be handled before this line");
407 DCmdMark mark(command);
408 command->parse(&line, delim, CHECK);
409 command->execute(source, CHECK);
410 }
411 count++;
412 }
413 }
414
415 void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
416 _dcmdparser.parse(line, delim, CHECK);
417 }
418
419 void DCmdWithParser::print_help(const char* name) const {
420 _dcmdparser.print_help(output(), name);
421 }
422
423 void DCmdWithParser::reset(TRAPS) {
424 _dcmdparser.reset(CHECK);
425 }
426
427 void DCmdWithParser::cleanup() {
428 _dcmdparser.cleanup();
429 }
430
431 GrowableArray<const char*>* DCmdWithParser::argument_name_array() const {
432 return _dcmdparser.argument_name_array();
433 }
434
435 GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() const {
436 return _dcmdparser.argument_info_array();
437 }
438
439 void DCmdFactory::push_jmx_notification_request() {
440 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
441 _has_pending_jmx_notification = true;
442 Service_lock->notify_all();
443 }
444
445 void DCmdFactory::send_notification(TRAPS) {
446 DCmdFactory::send_notification_internal(THREAD);
447 // Clearing pending exception to avoid premature termination of
448 // the service thread
449 if (HAS_PENDING_EXCEPTION) {
450 CLEAR_PENDING_EXCEPTION;
451 }
452 }
453 void DCmdFactory::send_notification_internal(TRAPS) {
454 ResourceMark rm(THREAD);
455 HandleMark hm(THREAD);
503 if(factory->export_flags() & source) {
504 return factory;
505 } else {
506 return NULL;
507 }
508 }
509 factory = factory->_next;
510 }
511 return NULL;
512 }
513
514 int DCmdFactory::register_DCmdFactory(DCmdFactory* factory) {
515 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
516 factory->_next = _DCmdFactoryList;
517 _DCmdFactoryList = factory;
518 if (_send_jmx_notification && !factory->_hidden
519 && (factory->_export_flags & DCmd_Source_MBean)) {
520 DCmdFactory::push_jmx_notification_request();
521 }
522 return 0; // Actually, there's no checks for duplicates
523 }
524
525 DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line,
526 outputStream* out, TRAPS) {
527 DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len());
528 if (f != NULL) {
529 if (!f->is_enabled()) {
530 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
531 f->disabled_message());
532 }
533 return f->create_resource_instance(out);
534 }
535 THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
536 "Unknown diagnostic command");
537 }
538
539 GrowableArray<const char*>* DCmdFactory::DCmd_list(DCmdSource source) {
540 MutexLockerEx ml(_dcmdFactory_lock, Mutex::_no_safepoint_check_flag);
541 GrowableArray<const char*>* array = new GrowableArray<const char*>();
542 DCmdFactory* factory = _DCmdFactoryList;
|