src/share/vm/services/diagnosticArgument.cpp

Thu, 27 Dec 2018 11:43:33 +0800

author
aoqi
date
Thu, 27 Dec 2018 11:43:33 +0800
changeset 9448
73d689add964
parent 9327
f96fcd9e1e1b
parent 6876
710a3c8b516e
child 9931
fd44df5e3bc3
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "memory/allocation.inline.hpp"
aoqi@0 27 #include "memory/resourceArea.hpp"
aoqi@0 28 #include "runtime/thread.hpp"
aoqi@0 29 #include "services/diagnosticArgument.hpp"
aoqi@0 30
aoqi@0 31 void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
aoqi@0 32 /* NOTE:Some argument types doesn't require a value,
aoqi@0 33 * for instance boolean arguments: "enableFeatureX". is
aoqi@0 34 * equivalent to "enableFeatureX=true". In these cases,
aoqi@0 35 * str will be null. This is perfectly valid.
aoqi@0 36 * All argument types must perform null checks on str.
aoqi@0 37 */
aoqi@0 38
aoqi@0 39 if (is_set() && !allow_multiple()) {
aoqi@0 40 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 41 "Duplicates in diagnostic command arguments\n");
aoqi@0 42 }
aoqi@0 43 parse_value(str, len, CHECK);
aoqi@0 44 set_is_set(true);
aoqi@0 45 }
aoqi@0 46
aoqi@0 47 void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) {
aoqi@0 48 jio_snprintf(buf, len, INT64_FORMAT, l);
aoqi@0 49 }
aoqi@0 50
aoqi@0 51 void GenDCmdArgument::to_string(bool b, char* buf, size_t len) {
aoqi@0 52 jio_snprintf(buf, len, b ? "true" : "false");
aoqi@0 53 }
aoqi@0 54
aoqi@0 55 void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) {
aoqi@0 56 jio_snprintf(buf, len, INT64_FORMAT, n._nanotime);
aoqi@0 57 }
aoqi@0 58
aoqi@0 59 void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) {
aoqi@0 60 jio_snprintf(buf, len, INT64_FORMAT, m._size);
aoqi@0 61 }
aoqi@0 62
aoqi@0 63 void GenDCmdArgument::to_string(char* c, char* buf, size_t len) {
aoqi@0 64 jio_snprintf(buf, len, "%s", (c != NULL) ? c : "");
aoqi@0 65 }
aoqi@0 66
aoqi@0 67 void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) {
aoqi@0 68 int length = f->array()->length();
aoqi@0 69 size_t written = 0;
aoqi@0 70 buf[0] = 0;
aoqi@0 71 for (int i = 0; i < length; i++) {
aoqi@0 72 char* next_str = f->array()->at(i);
aoqi@0 73 size_t next_size = strlen(next_str);
aoqi@0 74 //Check if there's room left to write next element
aoqi@0 75 if (written + next_size > len) {
aoqi@0 76 return;
aoqi@0 77 }
aoqi@0 78 //Actually write element
aoqi@0 79 strcat(buf, next_str);
aoqi@0 80 written += next_size;
aoqi@0 81 //Check if there's room left for the comma
aoqi@0 82 if (i < length-1 && len - written > 0) {
aoqi@0 83 strcat(buf, ",");
aoqi@0 84 }
aoqi@0 85 }
aoqi@0 86 }
aoqi@0 87
aoqi@0 88 template <> void DCmdArgument<jlong>::parse_value(const char* str,
aoqi@0 89 size_t len, TRAPS) {
aoqi@0 90 int scanned = -1;
aoqi@0 91 if (str == NULL
kevinw@9327 92 || sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1
aoqi@0 93 || (size_t)scanned != len)
aoqi@0 94 {
aoqi@0 95 ResourceMark rm;
aoqi@0 96
aoqi@0 97 char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
aoqi@0 98 strncpy(buf, str, len);
aoqi@0 99 buf[len] = '\0';
aoqi@0 100 Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 101 "Integer parsing error in command argument '%s'. Could not parse: %s.", _name, buf);
aoqi@0 102 }
aoqi@0 103 }
aoqi@0 104
aoqi@0 105 template <> void DCmdArgument<jlong>::init_value(TRAPS) {
aoqi@0 106 if (has_default()) {
aoqi@0 107 this->parse_value(_default_string, strlen(_default_string), THREAD);
aoqi@0 108 if (HAS_PENDING_EXCEPTION) {
aoqi@0 109 fatal("Default string must be parseable");
aoqi@0 110 }
aoqi@0 111 } else {
aoqi@0 112 set_value(0);
aoqi@0 113 }
aoqi@0 114 }
aoqi@0 115
aoqi@0 116 template <> void DCmdArgument<jlong>::destroy_value() { }
aoqi@0 117
aoqi@0 118 template <> void DCmdArgument<bool>::parse_value(const char* str,
aoqi@0 119 size_t len, TRAPS) {
aoqi@0 120 // len is the length of the current token starting at str
aoqi@0 121 if (len == 0) {
aoqi@0 122 set_value(true);
aoqi@0 123 } else {
aoqi@0 124 if (len == strlen("true") && strncasecmp(str, "true", len) == 0) {
aoqi@0 125 set_value(true);
aoqi@0 126 } else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) {
aoqi@0 127 set_value(false);
aoqi@0 128 } else {
aoqi@0 129 ResourceMark rm;
aoqi@0 130
aoqi@0 131 char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
aoqi@0 132 strncpy(buf, str, len);
aoqi@0 133 buf[len] = '\0';
aoqi@0 134 Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 135 "Boolean parsing error in command argument '%s'. Could not parse: %s.", _name, buf);
aoqi@0 136 }
aoqi@0 137 }
aoqi@0 138 }
aoqi@0 139
aoqi@0 140 template <> void DCmdArgument<bool>::init_value(TRAPS) {
aoqi@0 141 if (has_default()) {
aoqi@0 142 this->parse_value(_default_string, strlen(_default_string), THREAD);
aoqi@0 143 if (HAS_PENDING_EXCEPTION) {
aoqi@0 144 fatal("Default string must be parsable");
aoqi@0 145 }
aoqi@0 146 } else {
aoqi@0 147 set_value(false);
aoqi@0 148 }
aoqi@0 149 }
aoqi@0 150
aoqi@0 151 template <> void DCmdArgument<bool>::destroy_value() { }
aoqi@0 152
aoqi@0 153 template <> void DCmdArgument<char*>::parse_value(const char* str,
aoqi@0 154 size_t len, TRAPS) {
aoqi@0 155 if (str == NULL) {
aoqi@0 156 _value = NULL;
aoqi@0 157 } else {
aoqi@0 158 _value = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
aoqi@0 159 strncpy(_value, str, len);
aoqi@0 160 _value[len] = 0;
aoqi@0 161 }
aoqi@0 162 }
aoqi@0 163
aoqi@0 164 template <> void DCmdArgument<char*>::init_value(TRAPS) {
aoqi@0 165 if (has_default() && _default_string != NULL) {
aoqi@0 166 this->parse_value(_default_string, strlen(_default_string), THREAD);
aoqi@0 167 if (HAS_PENDING_EXCEPTION) {
aoqi@0 168 fatal("Default string must be parsable");
aoqi@0 169 }
aoqi@0 170 } else {
aoqi@0 171 set_value(NULL);
aoqi@0 172 }
aoqi@0 173 }
aoqi@0 174
aoqi@0 175 template <> void DCmdArgument<char*>::destroy_value() {
aoqi@0 176 if (_value != NULL) {
aoqi@0 177 FREE_C_HEAP_ARRAY(char, _value, mtInternal);
aoqi@0 178 set_value(NULL);
aoqi@0 179 }
aoqi@0 180 }
aoqi@0 181
aoqi@0 182 template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str,
aoqi@0 183 size_t len, TRAPS) {
aoqi@0 184 if (str == NULL) {
aoqi@0 185 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 186 "Integer parsing error nanotime value: syntax error, value is null");
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 int argc = sscanf(str, JLONG_FORMAT, &_value._time);
aoqi@0 190 if (argc != 1) {
aoqi@0 191 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 192 "Integer parsing error nanotime value: syntax error");
aoqi@0 193 }
aoqi@0 194 size_t idx = 0;
aoqi@0 195 while(idx < len && isdigit(str[idx])) {
aoqi@0 196 idx++;
aoqi@0 197 }
aoqi@0 198 if (idx == len) {
aoqi@0 199 // only accept missing unit if the value is 0
aoqi@0 200 if (_value._time != 0) {
aoqi@0 201 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 202 "Integer parsing error nanotime value: unit required");
aoqi@0 203 } else {
aoqi@0 204 _value._nanotime = 0;
aoqi@0 205 strcpy(_value._unit, "ns");
aoqi@0 206 return;
aoqi@0 207 }
aoqi@0 208 } else if(len - idx > 2) {
aoqi@0 209 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 210 "Integer parsing error nanotime value: illegal unit");
aoqi@0 211 } else {
aoqi@0 212 strncpy(_value._unit, &str[idx], len - idx);
aoqi@0 213 /*Write an extra null termination. This is safe because _value._unit
aoqi@0 214 * is declared as char[3], and length is checked to be not larger than
aoqi@0 215 * two above. Also, this is necessary, since length might be 1, and the
aoqi@0 216 * default value already in the string is ns, which is two chars.
aoqi@0 217 */
aoqi@0 218 _value._unit[len-idx] = '\0';
aoqi@0 219 }
aoqi@0 220
aoqi@0 221 if (strcmp(_value._unit, "ns") == 0) {
aoqi@0 222 _value._nanotime = _value._time;
aoqi@0 223 } else if (strcmp(_value._unit, "us") == 0) {
aoqi@0 224 _value._nanotime = _value._time * 1000;
aoqi@0 225 } else if (strcmp(_value._unit, "ms") == 0) {
aoqi@0 226 _value._nanotime = _value._time * 1000 * 1000;
aoqi@0 227 } else if (strcmp(_value._unit, "s") == 0) {
aoqi@0 228 _value._nanotime = _value._time * 1000 * 1000 * 1000;
aoqi@0 229 } else if (strcmp(_value._unit, "m") == 0) {
aoqi@0 230 _value._nanotime = _value._time * 60 * 1000 * 1000 * 1000;
aoqi@0 231 } else if (strcmp(_value._unit, "h") == 0) {
aoqi@0 232 _value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000;
aoqi@0 233 } else if (strcmp(_value._unit, "d") == 0) {
aoqi@0 234 _value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000;
aoqi@0 235 } else {
aoqi@0 236 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 237 "Integer parsing error nanotime value: illegal unit");
aoqi@0 238 }
aoqi@0 239 }
aoqi@0 240
aoqi@0 241 template <> void DCmdArgument<NanoTimeArgument>::init_value(TRAPS) {
aoqi@0 242 if (has_default()) {
aoqi@0 243 this->parse_value(_default_string, strlen(_default_string), THREAD);
aoqi@0 244 if (HAS_PENDING_EXCEPTION) {
aoqi@0 245 fatal("Default string must be parsable");
aoqi@0 246 }
aoqi@0 247 } else {
aoqi@0 248 _value._time = 0;
aoqi@0 249 _value._nanotime = 0;
aoqi@0 250 strcpy(_value._unit, "ns");
aoqi@0 251 }
aoqi@0 252 }
aoqi@0 253
aoqi@0 254 template <> void DCmdArgument<NanoTimeArgument>::destroy_value() { }
aoqi@0 255
aoqi@0 256 // WARNING StringArrayArgument can only be used as an option, it cannot be
aoqi@0 257 // used as an argument with the DCmdParser
aoqi@0 258
aoqi@0 259 template <> void DCmdArgument<StringArrayArgument*>::parse_value(const char* str,
aoqi@0 260 size_t len, TRAPS) {
aoqi@0 261 _value->add(str,len);
aoqi@0 262 }
aoqi@0 263
aoqi@0 264 template <> void DCmdArgument<StringArrayArgument*>::init_value(TRAPS) {
aoqi@0 265 _value = new StringArrayArgument();
aoqi@0 266 _allow_multiple = true;
aoqi@0 267 if (has_default()) {
aoqi@0 268 fatal("StringArrayArgument cannot have default value");
aoqi@0 269 }
aoqi@0 270 }
aoqi@0 271
aoqi@0 272 template <> void DCmdArgument<StringArrayArgument*>::destroy_value() {
aoqi@0 273 if (_value != NULL) {
aoqi@0 274 delete _value;
aoqi@0 275 set_value(NULL);
aoqi@0 276 }
aoqi@0 277 }
aoqi@0 278
aoqi@0 279 template <> void DCmdArgument<MemorySizeArgument>::parse_value(const char* str,
aoqi@0 280 size_t len, TRAPS) {
aoqi@0 281 if (str == NULL) {
aoqi@0 282 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 283 "Integer parsing error nanotime value: syntax error");
aoqi@0 284 }
aoqi@0 285
aoqi@0 286 if (*str == '-') {
aoqi@0 287 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 288 "Parsing error memory size value: negative values not allowed");
aoqi@0 289 }
aoqi@0 290 int res = sscanf(str, UINT64_FORMAT "%c", &_value._val, &_value._multiplier);
aoqi@0 291 if (res == 2) {
aoqi@0 292 switch (_value._multiplier) {
aoqi@0 293 case 'k': case 'K':
aoqi@0 294 _value._size = _value._val * 1024;
aoqi@0 295 break;
aoqi@0 296 case 'm': case 'M':
aoqi@0 297 _value._size = _value._val * 1024 * 1024;
aoqi@0 298 break;
aoqi@0 299 case 'g': case 'G':
aoqi@0 300 _value._size = _value._val * 1024 * 1024 * 1024;
aoqi@0 301 break;
aoqi@0 302 default:
aoqi@0 303 _value._size = _value._val;
aoqi@0 304 _value._multiplier = ' ';
aoqi@0 305 //default case should be to break with no error, since user
aoqi@0 306 //can write size in bytes, or might have a delimiter and next arg
aoqi@0 307 break;
aoqi@0 308 }
aoqi@0 309 } else if (res == 1) {
aoqi@0 310 _value._size = _value._val;
aoqi@0 311 } else {
aoqi@0 312 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
aoqi@0 313 "Parsing error memory size value: invalid value");
aoqi@0 314 }
aoqi@0 315 }
aoqi@0 316
aoqi@0 317 template <> void DCmdArgument<MemorySizeArgument>::init_value(TRAPS) {
aoqi@0 318 if (has_default()) {
aoqi@0 319 this->parse_value(_default_string, strlen(_default_string), THREAD);
aoqi@0 320 if (HAS_PENDING_EXCEPTION) {
aoqi@0 321 fatal("Default string must be parsable");
aoqi@0 322 }
aoqi@0 323 } else {
aoqi@0 324 _value._size = 0;
aoqi@0 325 _value._val = 0;
aoqi@0 326 _value._multiplier = ' ';
aoqi@0 327 }
aoqi@0 328 }
aoqi@0 329
aoqi@0 330 template <> void DCmdArgument<MemorySizeArgument>::destroy_value() { }

mercurial