xref: /illumos-gate/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Option.java (revision 3ce5372277f4657ad0e52d36c979527c4ca22de2)
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