1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 package org.opensolaris.os.dtrace; 27 28 import java.io.Serializable; 29 import java.io.ObjectInputStream; 30 import java.io.InvalidObjectException; 31 import java.io.IOException; 32 import java.beans.*; 33 34 /** 35 * A DTrace option and its value. Compile-time options must be set 36 * before calling {@code Consumer} {@link Consumer#compile(String 37 * program, String[] macroArgs) compile(String program, ...)} or {@link 38 * Consumer#compile(File program, String[] macroArgs) compile(File 39 * program, ...)} in order to affect program compilation. Runtime 40 * options may be set anytime before calling {@code Consumer} {@link 41 * Consumer#go() go()}, and some of them may be changed while a consumer 42 * is running. 43 * <p> 44 * See the <a 45 * href=http://dtrace.org/guide/chp-opt.html> 46 * <b>Options and Tunables</b></a> chapter of the <i>Dynamic 47 * Tracing Guide</i>. 48 * <p> 49 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 50 * 51 * @author Tom Erickson 52 */ 53 public final class Option implements Serializable { 54 static final long serialVersionUID = 2734100173861424920L; 55 56 /** 57 * Value returned by {@link Consumer#getOption(String option)} when 58 * the given boolean option is unset. 59 */ 60 public static final long UNSET = -2L; 61 62 /** 63 * Value returned by {@link Consumer#getOption(String option)} for 64 * the {@link #bufpolicy} option when the {@link #VALUE_RING ring} 65 * buffer policy is set. 66 */ 67 public static final long BUFPOLICY_RING = 0L; 68 69 /** 70 * Value returned by {@link Consumer#getOption(String option)} for 71 * the {@link #bufpolicy} option when the {@link #VALUE_FILL fill} 72 * buffer policy is set. 73 */ 74 public static final long BUFPOLICY_FILL = 1L; 75 76 /** 77 * Value returned by {@link Consumer#getOption(String option)} for 78 * the {@link #bufpolicy} option when the default {@link 79 * #VALUE_SWITCH switch} buffer policy is set. 80 */ 81 public static final long BUFPOLICY_SWITCH = 2L; 82 83 /** 84 * Value returned by {@link Consumer#getOption(String option)} for 85 * the {@link #bufresize} option when the default {@link #VALUE_AUTO 86 * auto} buffer resize policy is set. 87 */ 88 public static final long BUFRESIZE_AUTO = 0L; 89 90 /** 91 * Value returned by {@link Consumer#getOption(String option)} for 92 * the {@link #bufresize} option when the {@link #VALUE_MANUAL 93 * manual} buffer resize policy is set. 94 */ 95 public static final long BUFRESIZE_MANUAL = 1L; 96 97 static { 98 try { 99 BeanInfo info = Introspector.getBeanInfo(Option.class); 100 PersistenceDelegate persistenceDelegate = 101 new DefaultPersistenceDelegate( 102 new String[] {"name", "value"}) 103 { 104 /* 105 * Need to prevent DefaultPersistenceDelegate from using 106 * overridden equals() method, resulting in a 107 * StackOverFlowError. Revert to PersistenceDelegate 108 * implementation. See 109 * http://forum.java.sun.com/thread.jspa?threadID= 110 * 477019&tstart=135 111 */ 112 protected boolean 113 mutatesTo(Object oldInstance, Object newInstance) 114 { 115 return (newInstance != null && oldInstance != null && 116 oldInstance.getClass() == newInstance.getClass()); 117 } 118 }; 119 BeanDescriptor d = info.getBeanDescriptor(); 120 d.setValue("persistenceDelegate", persistenceDelegate); 121 } catch (IntrospectionException e) { 122 System.out.println(e); 123 } 124 } 125 126 // 127 // See lib/libdtrace/common/dt_options.c 128 // 129 130 /** 131 * Gets a size option value indicating the given number of 132 * kilobytes. 133 * 134 * @param n number of kilobytes 135 * @return size option value indicating the given number of 136 * kilobytes 137 */ 138 public static String kb(int n)139 kb(int n) 140 { 141 return (Integer.toString(n) + "k"); 142 } 143 144 /** 145 * Gets a size option value indicating the given number of 146 * megabytes. 147 * 148 * @param n number of megabytes 149 * @return size option value indicating the given number of 150 * megabytes 151 */ 152 public static String mb(int n)153 mb(int n) 154 { 155 return (Integer.toString(n) + "m"); 156 } 157 158 /** 159 * Gets a size option value indicating the given number of 160 * gigabytes. 161 * 162 * @param n number of gigabytes 163 * @return size option value indicating the given number of 164 * gigabytes 165 */ 166 public static String gb(int n)167 gb(int n) 168 { 169 return (Integer.toString(n) + "g"); 170 } 171 172 /** 173 * Gets a size option value indicating the given number of 174 * terabytes. 175 * 176 * @param n number of terabytes 177 * @return size option value indicating the given number of 178 * terabytes 179 */ 180 public static String tb(int n)181 tb(int n) 182 { 183 return (Integer.toString(n) + "t"); 184 } 185 186 /** 187 * Gets a time option value indicating the given number of 188 * nanoseconds. 189 * 190 * @param n number of nanoseconds 191 * @return time option value indicating the given number of 192 * nanoseconds 193 */ 194 public static String nanos(int n)195 nanos(int n) 196 { 197 return (Integer.toString(n) + "ns"); 198 } 199 200 /** 201 * Gets a time option value indicating the given number of 202 * microseconds. 203 * 204 * @param n number of microseconds 205 * @return time option value indicating the given number of 206 * microseconds 207 */ 208 public static String micros(int n)209 micros(int n) 210 { 211 return (Integer.toString(n) + "us"); 212 } 213 214 /** 215 * Gets a time option value indicating the given number of 216 * milliseconds. 217 * 218 * @param n number of milliseconds 219 * @return time option value indicating the given number of 220 * milliseconds 221 */ 222 public static String millis(int n)223 millis(int n) 224 { 225 return (Integer.toString(n) + "ms"); 226 } 227 228 /** 229 * Gets a time option value indicating the given number of seconds. 230 * 231 * @param n number of seconds 232 * @return time option value indicating the given number of seconds 233 */ 234 public static String seconds(int n)235 seconds(int n) 236 { 237 return (Integer.toString(n) + "s"); 238 } 239 240 /** 241 * Gets a time option value indicating the given number of minutes. 242 * 243 * @param n number of minutes 244 * @return time option value indicating the given number of minutes 245 */ 246 public static String minutes(int n)247 minutes(int n) 248 { 249 return (Integer.toString(n) + "m"); 250 } 251 252 /** 253 * Gets a time option value indicating the given number of hours. 254 * 255 * @param n number of hours 256 * @return time option value indicating the given number of hours 257 */ 258 public static String hours(int n)259 hours(int n) 260 { 261 return (Integer.toString(n) + "h"); 262 } 263 264 /** 265 * Gets a time option value indicating the given number of days. 266 * 267 * @param n number of days 268 * @return time option value indicating the given number of days 269 */ 270 public static String days(int n)271 days(int n) 272 { 273 return (Integer.toString(n) + "d"); 274 } 275 276 /** 277 * Gets a time option value indicating the given rate per second. 278 * 279 * @param n number of cycles per second (hertz) 280 * @return time option value indicating rate per second 281 */ 282 public static String hz(int n)283 hz(int n) 284 { 285 return (Integer.toString(n) + "hz"); 286 } 287 288 /** 289 * May be passed to {@link Consumer#setOption(String option, String 290 * value)} to set a boolean option such as {@link #flowindent}. 291 * However, a more convenient way to set boolean options is {@link 292 * Consumer#setOption(String option)}. 293 */ 294 public static final String VALUE_SET = "set"; 295 296 /** 297 * May be passed to {@link Consumer#setOption(String option, String 298 * value)} to unset a boolean option such as {@link #flowindent}. 299 * However, a more convenient way to unset boolean options is {@link 300 * Consumer#unsetOption(String option)}. 301 */ 302 public static final String VALUE_UNSET = "unset"; 303 304 /** 305 * {@link #bufpolicy} value: use {@code ring} principal buffer 306 * policy. 307 */ 308 public static final String VALUE_RING = "ring"; 309 /** 310 * {@link #bufpolicy} value: use {@code fill} principal buffer 311 * policy. 312 */ 313 public static final String VALUE_FILL = "fill"; 314 /** 315 * {@link #bufpolicy} default value: use {@code switch} principal 316 * buffer policy. 317 */ 318 public static final String VALUE_SWITCH = "switch"; 319 320 /** 321 * {@link #bufresize} default value: use {@code auto} buffer 322 * resizing policy. 323 */ 324 public static final String VALUE_AUTO = "auto"; 325 /** 326 * {@link #bufresize} value: use {@code manual} buffer resizing 327 * policy. 328 */ 329 public static final String VALUE_MANUAL = "manual"; 330 331 // 332 // See lib/libdtrace/common/dt_options.c 333 // 334 335 /** 336 * Set program attribute minimum (compile-time). The format of the 337 * option value is defined by the {@link 338 * InterfaceAttributes#toString()} method. 339 * 340 * @see Program#getInfo() 341 */ 342 public static final String amin = "amin"; 343 /** 344 * Do not require all macro args to be used (compile-time; no option 345 * value). 346 * 347 * @see Consumer#compile(String program, String[] macroArgs) 348 * @see Consumer#compile(File program, String[] macroArgs) 349 */ 350 public static final String argref = "argref"; 351 /** 352 * Run cpp(1) preprocessor on D script files (compile-time; no 353 * option value). 354 */ 355 public static final String cpp = "cpp"; 356 /** 357 * Used together with {@link #cpp} option, specifies which {@code 358 * cpp} to run by its pathname (compile-time). 359 */ 360 public static final String cpppath = "cpppath"; 361 /** 362 * Use zero (0) or empty string ("") as the value for unspecified macro args 363 * (compile-time; no option value). 364 * 365 * @see Consumer#compile(String program, String[] macroArgs) 366 * @see Consumer#compile(File program, String[] macroArgs) 367 */ 368 public static final String defaultargs = "defaultargs"; 369 /** 370 * Define symbol when invoking preprocessor (compile-time). 371 */ 372 public static final String define = "define"; 373 /** 374 * Permit compilation of empty D source files (compile-time; no 375 * option value). 376 */ 377 public static final String empty = "empty"; 378 /** 379 * Adds error tags to default error messages (compile-time; no 380 * option value). 381 */ 382 public static final String errtags = "errtags"; 383 /** 384 * Add include directory to preprocessor search path (compile-time). 385 */ 386 public static final String incdir = "incdir"; 387 /** 388 * Permit unresolved kernel symbols (compile-time; no option value). 389 */ 390 public static final String knodefs = "knodefs"; 391 /** 392 * Add library directory to library search path (compile-time). 393 */ 394 public static final String libdir = "libdir"; 395 /** 396 * Specify ISO C conformance settings for preprocessor 397 * (compile-time). 398 */ 399 public static final String stdc = "stdc"; 400 /** 401 * Undefine symbol when invoking preprocessor (compile-time). 402 */ 403 public static final String undef = "undef"; 404 /** 405 * Permit unresolved user symbols (compile-time; no option value). 406 */ 407 public static final String unodefs = "unodefs"; 408 /** 409 * Request specific version of native DTrace library (compile-time). 410 */ 411 public static final String version = "version"; 412 /** 413 * Permit probe definitions that match zero probes (compile-time; no 414 * option value). 415 */ 416 public static final String zdefs = "zdefs"; 417 418 /** Rate of aggregation reading (time). Runtime option. */ 419 public static final String aggrate = "aggrate"; 420 /** Aggregation buffer size (size). Runtime option. */ 421 public static final String aggsize = "aggsize"; 422 /** 423 * Denotes that aggregation data should be sorted in tuple order, 424 * with ties broken by value order (no option value). Runtime 425 * option. 426 * 427 * @see AggregationRecord 428 * @see Option#aggsortkeypos 429 * @see Option#aggsortpos 430 * @see Option#aggsortrev 431 */ 432 public static final String aggsortkey = "aggsortkey"; 433 /** 434 * When multiple aggregation tuple elements are present, the 435 * position of the tuple element that should act as the primary sort 436 * key (zero-based index). Runtime option. 437 * 438 * @see Option#aggsortkey 439 * @see Option#aggsortpos 440 * @see Option#aggsortrev 441 */ 442 public static final String aggsortkeypos = "aggsortkeypos"; 443 /** 444 * When multiple aggregations are being printed, the position of the 445 * aggregation that should act as the primary sort key (zero-based 446 * index). Runtime option. 447 * <p> 448 * Here "position" refers to the position of the aggregation in the 449 * {@code printa()} argument list after the format string (if 450 * any). For example, given the following statement: 451 * <pre><code> 452 * printa("%d %@7d %@7d\n", @a, @b); 453 * </code></pre> 454 * setting {@code aggsortpos} to {@code "0"} indicates that output 455 * should be sorted using the values of {@code @a} as the primary 456 * sort key, while setting {@code aggsortpos} to {@code "1"} 457 * indicates that output should be sorted using the values of 458 * {@code @b} as the primary sort key. 459 * 460 * @see Option#aggsortkey 461 * @see Option#aggsortkeypos 462 * @see Option#aggsortrev 463 */ 464 public static final String aggsortpos = "aggsortpos"; 465 /** 466 * Denotes that aggregation data should be sorted in descending 467 * order (no option value). Runtime option. 468 * <p> 469 * The {@code aggsortrev} option is useful in combination with the 470 * {@code aggsortkey}, {@code aggsortkeypos}, and {@code aggsortpos} 471 * options, which define the ascending sort reversed by this option. 472 * 473 * @see Option#aggsortkey 474 * @see Option#aggsortkeypos 475 * @see Option#aggsortpos 476 */ 477 public static final String aggsortrev = "aggsortrev"; 478 /** Principal buffer size (size). Runtime option. */ 479 public static final String bufsize = "bufsize"; 480 /** 481 * Buffering policy ({@link #VALUE_SWITCH switch}, {@link 482 * #VALUE_FILL fill}, or {@link #VALUE_RING ring}). Runtime option. 483 * <p> 484 * See the <a 485 * href=http://dtrace.org/guide/chp-buf.html#chp-buf-2> 486 * <b>Principal Buffer Policies</b></a> section of the 487 * <b>Buffers and Buffering</b> chapter of the <i>Dynamic 488 * Tracing Guide</i>. 489 */ 490 public static final String bufpolicy = "bufpolicy"; 491 /** 492 * Buffer resizing policy ({@link #VALUE_AUTO auto} or {@link 493 * #VALUE_MANUAL manual}). Runtime option. 494 * <p> 495 * See the <a 496 * href=http://dtrace.org/guide/chp-buf.html#chp-buf-5> 497 * <b>Buffer Resizing Policy</b></a> section of the <b>Buffers 498 * and Buffering</b> chapter of the <i>Dynamic Tracing 499 * Guide</i>. 500 */ 501 public static final String bufresize = "bufresize"; 502 /** Cleaning rate (time). Runtime option. */ 503 public static final String cleanrate = "cleanrate"; 504 /** CPU on which to enable tracing (scalar). Runtime option. */ 505 public static final String cpu = "cpu"; 506 /** Permit destructive actions (no option value). Runtime option. */ 507 public static final String destructive = "destructive"; 508 /** Dynamic variable space size (size). Runtime option. */ 509 public static final String dynvarsize = "dynvarsize"; 510 /** 511 * Adds {@link Flow} information to generated {@link ProbeData} 512 * indicating direction of control flow (entry or return) across 513 * function boundaries and depth in call stack (no option value). 514 * Runtime option. 515 */ 516 public static final String flowindent = "flowindent"; 517 /** Number of speculations (scalar). Runtime option. */ 518 public static final String nspec = "nspec"; 519 /** 520 * Only output explicitly traced data (no option value). Makes no 521 * difference to generated {@link ProbeData}, but user apps may use 522 * the {@code quiet} flag as a rendering hint similar to the {@code 523 * -q} {@code dtrace(8)} command option. Runtime option. 524 */ 525 public static final String quiet = "quiet"; 526 /** Speculation buffer size (size). Runtime option. */ 527 public static final String specsize = "specsize"; 528 /** Number of stack frames (scalar). Runtime option. */ 529 public static final String stackframes = "stackframes"; 530 /** Rate of status checking (time). Runtime option. */ 531 public static final String statusrate = "statusrate"; 532 /** String size (size). Runtime option. */ 533 public static final String strsize = "strsize"; 534 /** Rate of buffer switching (time). Runtime option. */ 535 public static final String switchrate = "switchrate"; 536 /** Number of user stack frames (scalar). Runtime option. */ 537 public static final String ustackframes = "ustackframes"; 538 539 /** @serial */ 540 private final String name; 541 /** @serial */ 542 private final String value; 543 544 /** 545 * Creates an option without an associated value. The created 546 * boolean option has the value {@link Option#VALUE_SET}. To 547 * specify that the named option be unset, use {@link 548 * Option#VALUE_UNSET}. 549 * 550 * @param optionName DTrace option name 551 * @throws NullPointerException if the given option name is {@code 552 * null} 553 * @see #Option(String optionName, String optionValue) 554 */ 555 public Option(String optionName)556 Option(String optionName) 557 { 558 this(optionName, Option.VALUE_SET); 559 } 560 561 /** 562 * Creates an option with the given name and value. 563 * 564 * @param optionName DTrace option name 565 * @param optionValue DTrace option value 566 * @throws NullPointerException if the given option name or value is 567 * {@code null} 568 */ 569 public Option(String optionName, String optionValue)570 Option(String optionName, String optionValue) 571 { 572 name = optionName; 573 value = optionValue; 574 validate(); 575 } 576 577 private final void validate()578 validate() 579 { 580 if (name == null) { 581 throw new NullPointerException("option name is null"); 582 } 583 if (value == null) { 584 throw new NullPointerException("option value is null"); 585 } 586 } 587 588 /** 589 * Gets the option name. 590 * 591 * @return non-null option name 592 */ 593 public String getName()594 getName() 595 { 596 return name; 597 } 598 599 /** 600 * Gets the option value. 601 * 602 * @return option value, or {@code null} if no value is associated 603 * with the option 604 */ 605 public String getValue()606 getValue() 607 { 608 return value; 609 } 610 611 /** 612 * Compares the specified object with this option for equality. 613 * Defines equality as having equal names and values. 614 * 615 * @return {@code true} if and only if the specified object is an 616 * {@code Option} with the same name and the same value as this 617 * option. Option values are the same if they are both {@code null} 618 * or if they are equal as defined by {@link String#equals(Object o) 619 * String.equals()}. 620 */ 621 public boolean equals(Object o)622 equals(Object o) 623 { 624 if (o instanceof Option) { 625 Option opt = (Option)o; 626 return (name.equals(opt.name) && 627 value.equals(opt.value)); 628 } 629 return false; 630 } 631 632 /** 633 * Overridden to ensure that equal options have equal hashcodes. 634 */ 635 @Override 636 public int hashCode()637 hashCode() 638 { 639 int hash = 17; 640 hash = (37 * hash) + name.hashCode(); 641 hash = (37 * hash) + value.hashCode(); 642 return hash; 643 } 644 645 private void readObject(ObjectInputStream s)646 readObject(ObjectInputStream s) 647 throws IOException, ClassNotFoundException 648 { 649 s.defaultReadObject(); 650 // check invariants 651 try { 652 validate(); 653 } catch (Exception e) { 654 InvalidObjectException x = new InvalidObjectException( 655 e.getMessage()); 656 x.initCause(e); 657 throw x; 658 } 659 } 660 661 /** 662 * Gets a string representation of this option useful for logging 663 * and not intended for display. The exact details of the 664 * representation are unspecified and subject to change, but the 665 * following format may be regarded as typical: 666 * <pre><code> 667 * class-name[property1 = value1, property2 = value2] 668 * </code></pre> 669 */ 670 public String toString()671 toString() 672 { 673 StringBuilder buf = new StringBuilder(); 674 buf.append(Option.class.getName()); 675 buf.append("[name = "); 676 buf.append(name); 677 buf.append(", value = "); 678 buf.append(value); 679 buf.append(']'); 680 return buf.toString(); 681 } 682 } 683