diagnosticArgument.cpp revision 3941:79f492f184d0
1/* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 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/allocation.inline.hpp" 27#include "runtime/thread.hpp" 28#include "services/diagnosticArgument.hpp" 29 30void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) { 31 /* NOTE:Some argument types doesn't require a value, 32 * for instance boolean arguments: "enableFeatureX". is 33 * equivalent to "enableFeatureX=true". In these cases, 34 * str will be null. This is perfectly valid. 35 * All argument types must perform null checks on str. 36 */ 37 38 if (is_set() && !allow_multiple()) { 39 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 40 "Duplicates in diagnostic command arguments\n"); 41 } 42 parse_value(str, len, CHECK); 43 set_is_set(true); 44} 45 46void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) { 47 jio_snprintf(buf, len, INT64_FORMAT, l); 48} 49 50void GenDCmdArgument::to_string(bool b, char* buf, size_t len) { 51 jio_snprintf(buf, len, b ? "true" : "false"); 52} 53 54void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) { 55 jio_snprintf(buf, len, INT64_FORMAT, n._nanotime); 56} 57 58void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) { 59 jio_snprintf(buf, len, INT64_FORMAT, m._size); 60} 61 62void GenDCmdArgument::to_string(char* c, char* buf, size_t len) { 63 jio_snprintf(buf, len, "%s", c); 64} 65 66void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) { 67 int length = f->array()->length(); 68 size_t written = 0; 69 buf[0] = 0; 70 for (int i = 0; i < length; i++) { 71 char* next_str = f->array()->at(i); 72 size_t next_size = strlen(next_str); 73 //Check if there's room left to write next element 74 if (written + next_size > len) { 75 return; 76 } 77 //Actually write element 78 strcat(buf, next_str); 79 written += next_size; 80 //Check if there's room left for the comma 81 if (i < length-1 && len - written > 0) { 82 strcat(buf, ","); 83 } 84 } 85} 86 87template <> void DCmdArgument<jlong>::parse_value(const char* str, 88 size_t len, TRAPS) { 89 if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { 90 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 91 "Integer parsing error in diagnostic command arguments\n"); 92 } 93} 94 95template <> void DCmdArgument<jlong>::init_value(TRAPS) { 96 if (has_default()) { 97 this->parse_value(_default_string, strlen(_default_string), THREAD); 98 if (HAS_PENDING_EXCEPTION) { 99 fatal("Default string must be parsable"); 100 } 101 } else { 102 set_value(0); 103 } 104} 105 106template <> void DCmdArgument<jlong>::destroy_value() { } 107 108template <> void DCmdArgument<bool>::parse_value(const char* str, 109 size_t len, TRAPS) { 110 // len is the length of the current token starting at str 111 if (len == 0) { 112 set_value(true); 113 } else { 114 if (len == strlen("true") && strncasecmp(str, "true", len) == 0) { 115 set_value(true); 116 } else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) { 117 set_value(false); 118 } else { 119 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 120 "Boolean parsing error in diagnostic command arguments"); 121 } 122 } 123} 124 125template <> void DCmdArgument<bool>::init_value(TRAPS) { 126 if (has_default()) { 127 this->parse_value(_default_string, strlen(_default_string), THREAD); 128 if (HAS_PENDING_EXCEPTION) { 129 fatal("Default string must be parsable"); 130 } 131 } else { 132 set_value(false); 133 } 134} 135 136template <> void DCmdArgument<bool>::destroy_value() { } 137 138template <> void DCmdArgument<char*>::parse_value(const char* str, 139 size_t len, TRAPS) { 140 if (str == NULL) { 141 _value = NULL; 142 } else { 143 _value = NEW_C_HEAP_ARRAY(char, len+1, mtInternal); 144 strncpy(_value, str, len); 145 _value[len] = 0; 146 } 147} 148 149template <> void DCmdArgument<char*>::init_value(TRAPS) { 150 if (has_default() && _default_string != NULL) { 151 this->parse_value(_default_string, strlen(_default_string), THREAD); 152 if (HAS_PENDING_EXCEPTION) { 153 fatal("Default string must be parsable"); 154 } 155 } else { 156 set_value(NULL); 157 } 158} 159 160template <> void DCmdArgument<char*>::destroy_value() { 161 if (_value != NULL) { 162 FREE_C_HEAP_ARRAY(char, _value, mtInternal); 163 set_value(NULL); 164 } 165} 166 167template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str, 168 size_t len, TRAPS) { 169 if (str == NULL) { 170 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 171 "Integer parsing error nanotime value: syntax error"); 172 } 173 174 int argc = sscanf(str, INT64_FORMAT , &_value._time); 175 if (argc != 1) { 176 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 177 "Integer parsing error nanotime value: syntax error"); 178 } 179 size_t idx = 0; 180 while(idx < len && isdigit(str[idx])) { 181 idx++; 182 } 183 if (idx == len) { 184 // only accept missing unit if the value is 0 185 if (_value._time != 0) { 186 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 187 "Integer parsing error nanotime value: unit required"); 188 } else { 189 _value._nanotime = 0; 190 strcpy(_value._unit, "ns"); 191 return; 192 } 193 } else if(len - idx > 2) { 194 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 195 "Integer parsing error nanotime value: illegal unit"); 196 } else { 197 strncpy(_value._unit, &str[idx], len - idx); 198 /*Write an extra null termination. This is safe because _value._unit 199 * is declared as char[3], and length is checked to be not larger than 200 * two above. Also, this is necessary, since length might be 1, and the 201 * default value already in the string is ns, which is two chars. 202 */ 203 _value._unit[len-idx] = '\0'; 204 } 205 206 if (strcmp(_value._unit, "ns") == 0) { 207 _value._nanotime = _value._time; 208 } else if (strcmp(_value._unit, "us") == 0) { 209 _value._nanotime = _value._time * 1000; 210 } else if (strcmp(_value._unit, "ms") == 0) { 211 _value._nanotime = _value._time * 1000 * 1000; 212 } else if (strcmp(_value._unit, "s") == 0) { 213 _value._nanotime = _value._time * 1000 * 1000 * 1000; 214 } else if (strcmp(_value._unit, "m") == 0) { 215 _value._nanotime = _value._time * 60 * 1000 * 1000 * 1000; 216 } else if (strcmp(_value._unit, "h") == 0) { 217 _value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000; 218 } else if (strcmp(_value._unit, "d") == 0) { 219 _value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000; 220 } else { 221 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 222 "Integer parsing error nanotime value: illegal unit"); 223 } 224} 225 226template <> void DCmdArgument<NanoTimeArgument>::init_value(TRAPS) { 227 if (has_default()) { 228 this->parse_value(_default_string, strlen(_default_string), THREAD); 229 if (HAS_PENDING_EXCEPTION) { 230 fatal("Default string must be parsable"); 231 } 232 } else { 233 _value._time = 0; 234 _value._nanotime = 0; 235 strcmp(_value._unit, "ns"); 236 } 237} 238 239template <> void DCmdArgument<NanoTimeArgument>::destroy_value() { } 240 241// WARNING StringArrayArgument can only be used as an option, it cannot be 242// used as an argument with the DCmdParser 243 244template <> void DCmdArgument<StringArrayArgument*>::parse_value(const char* str, 245 size_t len, TRAPS) { 246 _value->add(str,len); 247} 248 249template <> void DCmdArgument<StringArrayArgument*>::init_value(TRAPS) { 250 _value = new StringArrayArgument(); 251 _allow_multiple = true; 252 if (has_default()) { 253 fatal("StringArrayArgument cannot have default value"); 254 } 255} 256 257template <> void DCmdArgument<StringArrayArgument*>::destroy_value() { 258 if (_value != NULL) { 259 delete _value; 260 set_value(NULL); 261 } 262} 263 264template <> void DCmdArgument<MemorySizeArgument>::parse_value(const char* str, 265 size_t len, TRAPS) { 266 if (str == NULL) { 267 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 268 "Integer parsing error nanotime value: syntax error"); 269 } 270 271 if (*str == '-') { 272 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 273 "Parsing error memory size value: negative values not allowed"); 274 } 275 int res = sscanf(str, UINT64_FORMAT "%c", &_value._val, &_value._multiplier); 276 if (res == 2) { 277 switch (_value._multiplier) { 278 case 'k': case 'K': 279 _value._size = _value._val * 1024; 280 break; 281 case 'm': case 'M': 282 _value._size = _value._val * 1024 * 1024; 283 break; 284 case 'g': case 'G': 285 _value._size = _value._val * 1024 * 1024 * 1024; 286 break; 287 default: 288 _value._size = _value._val; 289 _value._multiplier = ' '; 290 //default case should be to break with no error, since user 291 //can write size in bytes, or might have a delimiter and next arg 292 break; 293 } 294 } else if (res == 1) { 295 _value._size = _value._val; 296 } else { 297 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 298 "Parsing error memory size value: invalid value"); 299 } 300} 301 302template <> void DCmdArgument<MemorySizeArgument>::init_value(TRAPS) { 303 if (has_default()) { 304 this->parse_value(_default_string, strlen(_default_string), THREAD); 305 if (HAS_PENDING_EXCEPTION) { 306 fatal("Default string must be parsable"); 307 } 308 } else { 309 _value._size = 0; 310 _value._val = 0; 311 _value._multiplier = ' '; 312 } 313} 314 315template <> void DCmdArgument<MemorySizeArgument>::destroy_value() { } 316