Home | History | Annotate | Download | only in dtrace
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    572     Option(String optionName, String optionValue)
    573     {
    574 	name = optionName;
    575 	value = optionValue;
    576 	validate();
    577     }
    578 
    579     private final void
    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
    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
    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
    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
    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
    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
    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