fparain@3329: /* fparain@5047: * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. fparain@3329: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. fparain@3329: * fparain@3329: * This code is free software; you can redistribute it and/or modify it fparain@3329: * under the terms of the GNU General Public License version 2 only, as fparain@3329: * published by the Free Software Foundation. fparain@3329: * fparain@3329: * This code is distributed in the hope that it will be useful, but WITHOUT fparain@3329: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or fparain@3329: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License fparain@3329: * version 2 for more details (a copy is included in the LICENSE file that fparain@3329: * accompanied this code). fparain@3329: * fparain@3329: * You should have received a copy of the GNU General Public License version fparain@3329: * 2 along with this work; if not, write to the Free Software Foundation, fparain@3329: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. fparain@3329: * fparain@3329: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA fparain@3329: * or visit www.oracle.com if you need additional information or have any fparain@3329: * questions. fparain@3329: * fparain@3329: */ fparain@3329: fparain@3329: #ifndef SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP fparain@3329: #define SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP fparain@3329: fparain@3329: #include "classfile/vmSymbols.hpp" fparain@3329: #include "memory/allocation.hpp" fparain@3329: #include "runtime/arguments.hpp" fparain@3329: #include "runtime/os.hpp" fparain@3329: #include "runtime/vm_version.hpp" fparain@3329: #include "runtime/vmThread.hpp" fparain@3329: #include "utilities/ostream.hpp" fparain@3329: fparain@3329: fparain@5047: enum DCmdSource { fparain@5047: DCmd_Source_Internal = 0x01U, // invocation from the JVM fparain@5047: DCmd_Source_AttachAPI = 0x02U, // invocation via the attachAPI fparain@5047: DCmd_Source_MBean = 0x04U // invocation via a MBean fparain@5047: }; fparain@5047: fparain@5047: // Warning: strings referenced by the JavaPermission struct are passed to fparain@5047: // the native part of the JDK. Avoid use of dynamically allocated strings fparain@5047: // that could be de-allocated before the JDK native code had time to fparain@5047: // convert them into Java Strings. fparain@5047: struct JavaPermission { fparain@5047: const char* _class; fparain@5047: const char* _name; fparain@5047: const char* _action; fparain@5047: }; fparain@5047: fparain@3329: // CmdLine is the class used to handle a command line containing a single fparain@3329: // diagnostic command and its arguments. It provides methods to access the fparain@3329: // command name and the beginning of the arguments. The class is also fparain@3329: // able to identify commented command lines and the "stop" keyword fparain@3329: class CmdLine : public StackObj { fparain@3329: private: fparain@3329: const char* _cmd; fparain@3329: size_t _cmd_len; fparain@3329: const char* _args; fparain@3329: size_t _args_len; fparain@3329: public: fparain@3329: CmdLine(const char* line, size_t len, bool no_command_name); fparain@3329: const char* args_addr() const { return _args; } fparain@3329: size_t args_len() const { return _args_len; } fparain@3329: const char* cmd_addr() const { return _cmd; } fparain@3329: size_t cmd_len() const { return _cmd_len; } fparain@3329: bool is_empty() { return _cmd_len == 0; } fparain@3329: bool is_executable() { return is_empty() || _cmd[0] != '#'; } fparain@3329: bool is_stop() { return !is_empty() && strncmp("stop", _cmd, _cmd_len) == 0; } fparain@3329: }; fparain@3329: fparain@3329: // Iterator class taking a character string in input and returning a CmdLine fparain@3329: // instance for each command line. The argument delimiter has to be specified. fparain@3329: class DCmdIter : public StackObj { fparain@3329: friend class DCmd; fparain@3329: private: fparain@3329: const char* _str; fparain@3329: char _delim; fparain@3329: size_t _len; fparain@3329: size_t _cursor; fparain@3329: public: fparain@3329: fparain@3329: DCmdIter(const char* str, char delim) { fparain@3329: _str = str; fparain@3329: _delim = delim; fparain@3329: _len = strlen(str); fparain@3329: _cursor = 0; fparain@3329: } fparain@3329: bool has_next() { return _cursor < _len; } fparain@3329: CmdLine next() { fparain@3329: assert(_cursor <= _len, "Cannot iterate more"); fparain@3329: size_t n = _cursor; fparain@3329: while (n < _len && _str[n] != _delim) n++; fparain@3329: CmdLine line(&(_str[_cursor]), n - _cursor, false); fparain@3329: _cursor = n + 1; fparain@3329: // The default copy constructor of CmdLine is used to return a CmdLine fparain@3329: // instance to the caller. fparain@3329: return line; fparain@3329: } fparain@3329: }; fparain@3329: fparain@3329: // Iterator class to iterate over diagnostic command arguments fparain@3329: class DCmdArgIter : public ResourceObj { fparain@3329: const char* _buffer; fparain@3329: size_t _len; fparain@3329: size_t _cursor; fparain@3329: const char* _key_addr; fparain@3329: size_t _key_len; fparain@3329: const char* _value_addr; fparain@3329: size_t _value_len; fparain@3329: char _delim; fparain@3329: public: fparain@3329: DCmdArgIter(const char* buf, size_t len, char delim) { fparain@3329: _buffer = buf; fparain@3329: _len = len; fparain@3329: _delim = delim; fparain@3329: _cursor = 0; fparain@3329: } fparain@3329: bool next(TRAPS); fparain@3329: const char* key_addr() { return _key_addr; } fparain@3329: size_t key_length() { return _key_len; } fparain@3329: const char* value_addr() { return _value_addr; } fparain@3329: size_t value_length() { return _value_len; } fparain@3329: }; fparain@3329: fparain@3329: // A DCmdInfo instance provides a description of a diagnostic command. It is fparain@3329: // used to export the description to the JMX interface of the framework. fparain@3329: class DCmdInfo : public ResourceObj { fparain@3329: protected: fparain@5047: const char* _name; /* Name of the diagnostic command */ fparain@5047: const char* _description; /* Short description */ fparain@5047: const char* _impact; /* Impact on the JVM */ fparain@5047: JavaPermission _permission; /* Java Permission required to execute this command if any */ fparain@5047: int _num_arguments; /* Number of supported options or arguments */ fparain@5047: bool _is_enabled; /* True if the diagnostic command can be invoked, false otherwise */ fparain@3329: public: fparain@3329: DCmdInfo(const char* name, fparain@3329: const char* description, fparain@3329: const char* impact, fparain@5047: JavaPermission permission, fparain@3329: int num_arguments, fparain@3329: bool enabled) { fparain@3329: this->_name = name; fparain@3329: this->_description = description; fparain@3329: this->_impact = impact; fparain@5047: this->_permission = permission; fparain@3329: this->_num_arguments = num_arguments; fparain@3329: this->_is_enabled = enabled; fparain@3329: } fparain@3329: const char* name() const { return _name; } fparain@3329: const char* description() const { return _description; } fparain@3329: const char* impact() const { return _impact; } fparain@5047: JavaPermission permission() const { return _permission; } fparain@3329: int num_arguments() const { return _num_arguments; } fparain@3329: bool is_enabled() const { return _is_enabled; } fparain@3329: fparain@3329: static bool by_name(void* name, DCmdInfo* info); fparain@3329: }; fparain@3329: fparain@3329: // A DCmdArgumentInfo instance provides a description of a diagnostic command fparain@3329: // argument. It is used to export the description to the JMX interface of the fparain@3329: // framework. fparain@3329: class DCmdArgumentInfo : public ResourceObj { fparain@3329: protected: fparain@5047: const char* _name; /* Option/Argument name*/ fparain@5047: const char* _description; /* Short description */ fparain@5047: const char* _type; /* Type: STRING, BOOLEAN, etc. */ fparain@5047: const char* _default_string; /* Default value in a parsable string */ fparain@5047: bool _mandatory; /* True if the option/argument is mandatory */ fparain@5047: bool _option; /* True if it is an option, false if it is an argument */ fparain@5047: /* (see diagnosticFramework.hpp for option/argument definitions) */ fparain@5047: bool _multiple; /* True is the option can be specified several time */ fparain@5047: int _position; /* Expected position for this argument (this field is */ fparain@5047: /* meaningless for options) */ fparain@3329: public: fparain@3329: DCmdArgumentInfo(const char* name, const char* description, const char* type, fparain@5047: const char* default_string, bool mandatory, bool option, fparain@5047: bool multiple) { fparain@3329: this->_name = name; fparain@3329: this->_description = description; fparain@3329: this->_type = type; fparain@3329: this->_default_string = default_string; fparain@3329: this->_option = option; fparain@3329: this->_mandatory = mandatory; fparain@3329: this->_option = option; fparain@5047: this->_multiple = multiple; fparain@3329: this->_position = -1; fparain@3329: } fparain@3329: DCmdArgumentInfo(const char* name, const char* description, const char* type, fparain@3329: const char* default_string, bool mandatory, bool option, fparain@5047: bool multiple, int position) { fparain@3329: this->_name = name; fparain@3329: this->_description = description; fparain@3329: this->_type = type; fparain@3329: this->_default_string = default_string; fparain@3329: this->_option = option; fparain@3329: this->_mandatory = mandatory; fparain@3329: this->_option = option; fparain@5047: this->_multiple = multiple; fparain@3329: this->_position = position; fparain@3329: } fparain@3329: const char* name() const { return _name; } fparain@3329: const char* description() const { return _description; } fparain@3329: const char* type() const { return _type; } fparain@3329: const char* default_string() const { return _default_string; } fparain@3329: bool is_mandatory() const { return _mandatory; } fparain@3329: bool is_option() const { return _option; } fparain@5047: bool is_multiple() const { return _multiple; } fparain@3329: int position() const { return _position; } fparain@3329: }; fparain@3329: fparain@3329: // The DCmdParser class can be used to create an argument parser for a fparain@3329: // diagnostic command. It is not mandatory to use it to parse arguments. fparain@5047: // The DCmdParser parses a CmdLine instance according to the parameters that fparain@5047: // have been declared by its associated diagnostic command. A parameter can fparain@5047: // either be an option or an argument. Options are identified by the option name fparain@5047: // while arguments are identified by their position in the command line. The fparain@5047: // position of an argument is defined relative to all arguments passed on the fparain@5047: // command line, options are not considered when defining an argument position. fparain@5047: // The generic syntax of a diagnostic command is: fparain@5047: // fparain@5047: // [