src/share/vm/services/diagnosticArgument.cpp

Print this page
rev 3087 : 7141252: Diagnostic Framework Default parser fixes


  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 
  30 void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
  31   if (is_set()) {







  32     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
  33             "Duplicates in diagnostic command arguments");
  34   }
  35   parse_value(str, len, CHECK);
  36   set_is_set(true);
  37 }
  38 
  39 template <> void DCmdArgument<jlong>::parse_value(const char* str,
  40                                                   size_t len, TRAPS) {
  41   if (sscanf(str, INT64_FORMAT, &_value) != 1) {
  42     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
  43       "Integer parsing error in diagnostic command arguments");
  44   }
  45 }
  46 
  47 template <> void DCmdArgument<jlong>::init_value(TRAPS) {
  48   if (has_default()) {
  49     this->parse_value(_default_string, strlen(_default_string), THREAD);
  50     if (HAS_PENDING_EXCEPTION) {
  51       fatal("Default string must be parsable");
  52     }
  53   } else {
  54     set_value(0);
  55   }
  56 }
  57 
  58 template <> void DCmdArgument<jlong>::destroy_value() { }
  59 
  60 template <> void DCmdArgument<bool>::parse_value(const char* str,
  61                                                  size_t len, TRAPS) {
  62   // len is the length of the current token starting at str
  63   if (len == 0) {


  72         "Boolean parsing error in diagnostic command arguments");
  73     }
  74   }
  75 }
  76 
  77 template <> void DCmdArgument<bool>::init_value(TRAPS) {
  78   if (has_default()) {
  79     this->parse_value(_default_string, strlen(_default_string), THREAD);
  80     if (HAS_PENDING_EXCEPTION) {
  81       fatal("Default string must be parsable");
  82     }
  83   } else {
  84     set_value(false);
  85   }
  86 }
  87 
  88 template <> void DCmdArgument<bool>::destroy_value() { }
  89 
  90 template <> void DCmdArgument<char*>::parse_value(const char* str,
  91                                                   size_t len, TRAPS) {



  92   _value = NEW_C_HEAP_ARRAY(char, len+1);
  93   strncpy(_value, str, len);
  94   _value[len] = 0;

  95 }
  96 
  97 template <> void DCmdArgument<char*>::init_value(TRAPS) {
  98   if (has_default()) {
  99     this->parse_value(_default_string, strlen(_default_string), THREAD);
 100     if (HAS_PENDING_EXCEPTION) {
 101       fatal("Default string must be parsable");
 102     }
 103   } else {
 104     set_value(NULL);
 105   }
 106 }
 107 
 108 template <> void DCmdArgument<char*>::destroy_value() {
 109   if (_value != NULL) {
 110     FREE_C_HEAP_ARRAY(char, _value);
 111     set_value(NULL);
 112   }
 113 }
























































































































































  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 
  30 void 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 
  46 template <> void DCmdArgument<jlong>::parse_value(const char* str,
  47                                                   size_t len, TRAPS) {
  48     if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) {
  49     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
  50       "Integer parsing error in diagnostic command arguments\n");
  51   }
  52 }
  53 
  54 template <> void DCmdArgument<jlong>::init_value(TRAPS) {
  55   if (has_default()) {
  56     this->parse_value(_default_string, strlen(_default_string), THREAD);
  57     if (HAS_PENDING_EXCEPTION) {
  58       fatal("Default string must be parsable");
  59     }
  60   } else {
  61     set_value(0);
  62   }
  63 }
  64 
  65 template <> void DCmdArgument<jlong>::destroy_value() { }
  66 
  67 template <> void DCmdArgument<bool>::parse_value(const char* str,
  68                                                  size_t len, TRAPS) {
  69   // len is the length of the current token starting at str
  70   if (len == 0) {


  79         "Boolean parsing error in diagnostic command arguments");
  80     }
  81   }
  82 }
  83 
  84 template <> void DCmdArgument<bool>::init_value(TRAPS) {
  85   if (has_default()) {
  86     this->parse_value(_default_string, strlen(_default_string), THREAD);
  87     if (HAS_PENDING_EXCEPTION) {
  88       fatal("Default string must be parsable");
  89     }
  90   } else {
  91     set_value(false);
  92   }
  93 }
  94 
  95 template <> void DCmdArgument<bool>::destroy_value() { }
  96 
  97 template <> void DCmdArgument<char*>::parse_value(const char* str,
  98                                                   size_t len, TRAPS) {
  99   if (str == NULL) {
 100     _value = NULL;
 101   } else {
 102     _value = NEW_C_HEAP_ARRAY(char, len+1);
 103     strncpy(_value, str, len);
 104     _value[len] = 0;
 105   }
 106 }
 107 
 108 template <> void DCmdArgument<char*>::init_value(TRAPS) {
 109   if (has_default() && _default_string != NULL) {
 110     this->parse_value(_default_string, strlen(_default_string), THREAD);
 111     if (HAS_PENDING_EXCEPTION) {
 112      fatal("Default string must be parsable");
 113     }
 114   } else {
 115     set_value(NULL);
 116   }
 117 }
 118 
 119 template <> void DCmdArgument<char*>::destroy_value() {
 120   if (_value != NULL) {
 121     FREE_C_HEAP_ARRAY(char, _value);
 122     set_value(NULL);
 123   }
 124 }
 125 
 126 template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str,
 127                                                  size_t len, TRAPS) {
 128   if (str == NULL) {
 129     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 130               "Integer parsing error nanotime value: syntax error");
 131   }
 132 
 133   int argc = sscanf(str, INT64_FORMAT , &_value._time);
 134   if (argc != 1) {
 135     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 136               "Integer parsing error nanotime value: syntax error");
 137   }
 138   size_t idx = 0;
 139   while(idx < len && isdigit(str[idx])) {
 140     idx++;
 141   }
 142   if (idx == len) {
 143     // only accept missing unit if the value is 0
 144     if (_value._time != 0) {
 145       THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 146                 "Integer parsing error nanotime value: unit required");
 147     } else {
 148       _value._nanotime = 0;
 149       strcpy(_value._unit, "ns");
 150       return;
 151     }
 152   } else if(len - idx > 2) {
 153     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 154               "Integer parsing error nanotime value: illegal unit");
 155   } else {
 156     strncpy(_value._unit, &str[idx], len - idx);
 157     /*Write an extra null termination. This is safe because _value._unit
 158      * is declared as char[3], and length is checked to be not larger than
 159      * two above. Also, this is necessary, since length might be 1, and the
 160      * default value already in the string is ns, which is two chars.
 161      */
 162     _value._unit[len-idx] = '\0';
 163   }
 164 
 165   if (strcmp(_value._unit, "ns") == 0) {
 166     _value._nanotime = _value._time;
 167   } else if (strcmp(_value._unit, "us") == 0) {
 168     _value._nanotime = _value._time * 1000;
 169   } else if (strcmp(_value._unit, "ms") == 0) {
 170     _value._nanotime = _value._time * 1000 * 1000;
 171   } else if (strcmp(_value._unit, "s") == 0) {
 172     _value._nanotime = _value._time * 1000 * 1000 * 1000;
 173   } else if (strcmp(_value._unit, "m") == 0) {
 174     _value._nanotime = _value._time * 60 * 1000 * 1000 * 1000;
 175   } else if (strcmp(_value._unit, "h") == 0) {
 176     _value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000;
 177   } else if (strcmp(_value._unit, "d") == 0) {
 178     _value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000;
 179   } else {
 180      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 181                "Integer parsing error nanotime value: illegal unit");
 182   }
 183 }
 184 
 185 template <> void DCmdArgument<NanoTimeArgument>::init_value(TRAPS) {
 186   if (has_default()) {
 187     this->parse_value(_default_string, strlen(_default_string), THREAD);
 188     if (HAS_PENDING_EXCEPTION) {
 189       fatal("Default string must be parsable");
 190     }
 191   } else {
 192     _value._time = 0;
 193     _value._nanotime = 0;
 194     strcmp(_value._unit, "ns");
 195   }
 196 }
 197 
 198 template <> void DCmdArgument<NanoTimeArgument>::destroy_value() { }
 199 
 200 // WARNING StringArrayArgument can only be used as an option, it cannot be
 201 // used as an argument with the DCmdParser
 202 
 203 template <> void DCmdArgument<StringArrayArgument*>::parse_value(const char* str,
 204                                                   size_t len, TRAPS) {
 205   _value->add(str,len);
 206 }
 207 
 208 template <> void DCmdArgument<StringArrayArgument*>::init_value(TRAPS) {
 209   _value = new StringArrayArgument();
 210   _allow_multiple = true;
 211   if (has_default()) {
 212     fatal("StringArrayArgument cannot have default value");
 213   }
 214 }
 215 
 216 template <> void DCmdArgument<StringArrayArgument*>::destroy_value() {
 217   if (_value != NULL) {
 218     delete _value;
 219     set_value(NULL);
 220   }
 221 }
 222 
 223 template <> void DCmdArgument<MemorySizeArgument>::parse_value(const char* str,
 224                                                   size_t len, TRAPS) {
 225   if (str == NULL) {
 226     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 227               "Integer parsing error nanotime value: syntax error");
 228   }
 229 
 230   if (*str == '-') {
 231     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 232                "Parsing error memory size value: negative values not allowed");
 233   }
 234   int res = sscanf(str, "%" FORMAT64_MODIFIER "u%c", &_value._val, &_value._multiplier);
 235   if (res == 2) {
 236      switch (_value._multiplier) {
 237       case 'k': case 'K':
 238          _value._size = _value._val * 1024;
 239          break;
 240       case 'm': case 'M':
 241          _value._size = _value._val * 1024 * 1024;
 242          break;
 243       case 'g': case 'G':
 244          _value._size = _value._val * 1024 * 1024 * 1024;
 245          break;
 246        default:
 247          _value._size = _value._val;
 248          _value._multiplier = ' ';
 249          //default case should be to break with no error, since user
 250          //can write size in bytes, or might have a delimiter and next arg
 251          break;
 252      }
 253    } else if (res == 1) {
 254      _value._size = _value._val;
 255    } else {
 256      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
 257                "Parsing error memory size value: invalid value");
 258    }
 259 }
 260 
 261 template <> void DCmdArgument<MemorySizeArgument>::init_value(TRAPS) {
 262   if (has_default()) {
 263     this->parse_value(_default_string, strlen(_default_string), THREAD);
 264     if (HAS_PENDING_EXCEPTION) {
 265       fatal("Default string must be parsable");
 266     }
 267   } else {
 268     _value._size = 0;
 269     _value._val = 0;
 270     _value._multiplier = ' ';
 271   }
 272 }
 273 
 274 template <> void DCmdArgument<MemorySizeArgument>::destroy_value() { }