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