diff options
author | tomee <none@none> | 2008-03-03 13:42:58 -0800 |
---|---|---|
committer | tomee <none@none> | 2008-03-03 13:42:58 -0800 |
commit | e77b06d21580f630e0a7c437495ab283d3672828 (patch) | |
tree | 90e14035b187c2c826fa8999964d4cb538879f33 /usr/src/lib/libdtrace_jni/java | |
parent | faf8f9938fe55ca401d413444319f28f95998e42 (diff) | |
download | illumos-gate-e77b06d21580f630e0a7c437495ab283d3672828.tar.gz |
6545859 ERROR: /opt/SUNWdtrt/tst/common/java_api/tst.Bean.ksh stdout mismatch
6650894 'dtest -i java' errors
6652174 add "-target 1.5" javac flag to build dtest Java classes
6652183 add "-Xlint" javac flag to Java DTrace API build
6652217 Java DTrace API loses aggregation record order
6667597 Java DTrace API does not handle negative average in avg() action
6667606 Java DTrace API needs to support stddev() action
6668854 DTrace Java tests should run by default
6668856 dtest -u is useless
Diffstat (limited to 'usr/src/lib/libdtrace_jni/java')
15 files changed, 672 insertions, 45 deletions
diff --git a/usr/src/lib/libdtrace_jni/java/Makefile b/usr/src/lib/libdtrace_jni/java/Makefile index ad7d1a90cf..3ecad3d242 100644 --- a/usr/src/lib/libdtrace_jni/java/Makefile +++ b/usr/src/lib/libdtrace_jni/java/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -80,6 +80,7 @@ APICLASSPATH=$(CLASSES):$(APIJAVASRC) # javac flags JFLAGS= -g -d $(CLASSES) -sourcepath $(APICLASSPATH) -deprecation JFLAGS += -target 1.5 +JFLAGS += -Xlint # The default make rule for Java files COMPILE.java=$(JAVAC) $(JFLAGS) @@ -149,6 +150,7 @@ API_CLASSNAMES=\ ScalarRecord \ StackFrame \ StackValueRecord \ + StddevValue \ SumValue \ SymbolValueRecord \ Tuple \ diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregate.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregate.java index 856ccbb6ef..7954d630a2 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregate.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregate.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -67,6 +67,7 @@ public final class Aggregate implements Serializable // value of the getAggregations() method. private transient Map <String, Aggregation> map; + private transient int recordSequence; /** * Called by native code. @@ -88,12 +89,15 @@ public final class Aggregate implements Serializable * belonging to this aggregate * @throws NullPointerException if the given collection of * aggregations is {@code null} + * @throws IllegalArgumentException if the record ordinals of the + * given aggregations are invalid */ public Aggregate(long snaptimeNanos, Collection <Aggregation> aggregations) { snaptime = snaptimeNanos; mapAggregations(aggregations); + validate(); } // assumes map is not yet created @@ -105,6 +109,35 @@ public final class Aggregate implements Serializable map = new HashMap <String, Aggregation> (capacity, 1.0f); for (Aggregation a : aggregations) { map.put(a.getName(), a); + recordSequence += a.asMap().size(); + } + } + + private void + validate() + { + int capacity = (int)(((float)recordSequence * 3.0f) / 2.0f); + Set <Integer> ordinals = new HashSet <Integer> (capacity, 1.0f); + int ordinal, max = 0; + for (Aggregation a : map.values()) { + for (AggregationRecord r : a.asMap().values()) { + // Allow all ordinals to be zero for backward + // compatibility (allows XML decoding of aggregates that + // were encoded before the ordinal property was added). + if (!ordinals.add(ordinal = r.getOrdinal()) && (ordinal > 0)) { + throw new IllegalArgumentException( + "duplicate record ordinal: " + ordinal); + } + if (ordinal > max) { + max = ordinal; + } + } + } + if ((max > 0) && (max != (recordSequence - 1))) { + throw new IllegalArgumentException( + "The maximum record ordinal (" + max + ") does not " + + "equal the number of records (" + recordSequence + + ") minus one."); } } @@ -171,6 +204,61 @@ public final class Aggregate implements Serializable } /** + * Gets an unordered list of this aggregate's records. The list is + * sortable using {@link java.util.Collections#sort(List list, + * Comparator c)} with any user-defined ordering. Modifying the + * returned list has no effect on this aggregate. + * + * @return a newly created list that copies this aggregate's records + * by reference in no particular order + */ + public List <AggregationRecord> + getRecords() + { + List <AggregationRecord> list = + new ArrayList <AggregationRecord> (recordSequence); + for (Aggregation a : map.values()) { + list.addAll(a.asMap().values()); + } + return list; + } + + /** + * Gets an ordered list of this aggregate's records sequenced by + * their {@link AggregationRecord#getOrdinal() ordinal} property. + * Note that the unordered list returned by {@link #getRecords()} + * can easily be sorted by any arbitrary criteria, for example by + * key ascending: + * <pre><code> + * List <AggregationRecord> records = aggregate.getRecords(); + * Collections.sort(records, new Comparator <AggregationRecord> () { + * public int compare(AggregationRecord r1, AggregationRecord r2) { + * return r1.getTuple().compareTo(r2.getTuple()); + * } + * }); + * </code></pre> + * Use {@code getOrderedRecords()} instead of {@code getRecords()} + * when you want to list records as they would be ordered by {@code + * dtrace(1M)}. + * + * @return a newly created list of this aggregate's records + * in the order used by the native DTrace library + */ + public List <AggregationRecord> + getOrderedRecords() + { + List <AggregationRecord> list = getRecords(); + Collections.sort(list, new Comparator <AggregationRecord> () { + public int compare(AggregationRecord r1, AggregationRecord r2) { + int n1 = r1.getOrdinal(); + int n2 = r2.getOrdinal(); + return (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)); + } + }); + return list; + } + + /** * In the native DTrace library, the unnamed aggregation {@code @} * is given the name {@code _} (underbar). The Java DTrace API does * not expose this implementation detail but instead identifies the @@ -212,6 +300,7 @@ public final class Aggregate implements Serializable private void addRecord(String aggregationName, long aggid, AggregationRecord rec) { + rec.setOrdinal(recordSequence++); aggregationName = Aggregate.filterUnnamedAggregationName( aggregationName); Aggregation aggregation = getAggregation(aggregationName); @@ -246,6 +335,14 @@ public final class Aggregate implements Serializable // load serialized form into private map as a defensive copy mapAggregations(aggregations); // check class invariants after defensive copy + try { + validate(); + } catch (Exception e) { + InvalidObjectException x = new InvalidObjectException( + e.getMessage()); + x.initCause(e); + throw x; + } } /** diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregateSpec.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregateSpec.java index 3551bec9bf..3617ac9ea4 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregateSpec.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregateSpec.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -118,7 +118,7 @@ class AggregateSpec { if (includedAggregationNames == null) { return Collections. <String> emptySet(); } - return Collections.unmodifiableSet(includedAggregationNames); + return Collections. <String> unmodifiableSet(includedAggregationNames); } public Set <String> @@ -127,7 +127,7 @@ class AggregateSpec { if (clearedAggregationNames == null) { return Collections. <String> emptySet(); } - return Collections.unmodifiableSet(clearedAggregationNames); + return Collections. <String> unmodifiableSet(clearedAggregationNames); } public boolean diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregation.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregation.java index cb3f18af89..7a31f39c41 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregation.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Aggregation.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -192,14 +192,16 @@ public final class Aggregation implements Serializable { } /** - * Gets an unordered list of this aggregation's records. The list - * is easily sortable using {@link java.util.Collections#sort(List - * list, Comparator c)} provided any user-defined ordering. - * Modifying the returned list has no effect on this aggregation. - * Supports XML persistence. + * Gets an unordered list of this aggregation's records. The list is + * sortable using {@link java.util.Collections#sort(List list, + * Comparator c)} with any user-defined ordering. Modifying the + * returned list has no effect on this aggregation. Supports XML + * persistence. * * @return a newly created list that copies this aggregation's * records by reference in no particular order + * @see Aggregate#getRecords() + * @see Aggregate#getOrderedRecords() */ public List <AggregationRecord> getRecords() @@ -233,7 +235,7 @@ public final class Aggregation implements Serializable { public Map <Tuple, AggregationRecord> asMap() { - return Collections.unmodifiableMap(map); + return Collections. <Tuple, AggregationRecord> unmodifiableMap(map); } /** diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregationRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregationRecord.java index 13767f59e6..35fa877fbf 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregationRecord.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/AggregationRecord.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -40,14 +40,14 @@ import java.beans.*; * @author Tom Erickson */ public final class AggregationRecord implements Record, Serializable { - static final long serialVersionUID = -8439277589555814411L; + static final long serialVersionUID = -4367614268579702616L; static { try { BeanInfo info = Introspector.getBeanInfo(AggregationRecord.class); PersistenceDelegate persistenceDelegate = new DefaultPersistenceDelegate( - new String[] {"tuple", "value"}) + new String[] {"tuple", "value", "ordinal"}) { /* * Need to prevent DefaultPersistenceDelegate from using @@ -75,25 +75,51 @@ public final class AggregationRecord implements Record, Serializable { private Tuple tuple; /** @serial */ private AggregationValue value; + /** @serial */ + private int ordinal; + /** * Creates an aggregation record with the given key and value. * Supports XML persistence. * + * @see #AggregationRecord(Tuple tupleKey, AggregationValue + * recordValue, int n) + */ + public + AggregationRecord(Tuple tupleKey, AggregationValue recordValue) + { + // + // Called by native code, but public to support backwardly + // compatible XML encoding. + // + tuple = tupleKey; + value = recordValue; + validate(); + } + + /** + * Creates an aggregation record with the given key, value, and + * ordinal. Supports XML persistence. + * * @param tupleKey aggregation tuple, may be empty (see {@link * Tuple#EMPTY}) to indicate that this record's value belongs to an * unkeyed aggregation declared without square brackets, for * example: <pre> {@code @a = count();}</pre> * @param recordValue aggregated value associated with the given * tuple + * @param n ordinal from zero (first) to n-1 (last) within the + * {@link Aggregate} containing this record * @throws NullPointerException if the given key or value is * {@code null} + * @throws IllegalArgumentException if the given ordinal is negative */ public - AggregationRecord(Tuple tupleKey, AggregationValue recordValue) + AggregationRecord(Tuple tupleKey, AggregationValue recordValue, int n) { tuple = tupleKey; value = recordValue; + ordinal = n; validate(); } @@ -106,6 +132,9 @@ public final class AggregationRecord implements Record, Serializable { if (value == null) { throw new NullPointerException("value is null"); } + if (ordinal < 0) { + throw new IllegalArgumentException("ordinal is negative"); + } } /** @@ -138,6 +167,38 @@ public final class AggregationRecord implements Record, Serializable { } /** + * Gets the ordinal generated when this AggregationRecord was added + * to its containing {@link Aggregate} by the native DTrace library, + * from zero (first) to n-1 (last). The sequence described by an + * aggregate's record ordinals reflects the setting of the {@link + * Option#aggsortkey aggsortkey}, {@link Option#aggsortkeypos + * aggsortkeypos}, {@link Option#aggsortpos aggsortpos}, and {@link + * Option#aggsortrev aggsortrev} DTrace options and matches the way + * that the records would be ordered by {@code dtrace(1M)}. + * + * @return non-negative ordinal from zero (first) to n-1 (last) + * within the {@code Aggregate} containing this record + * @see Aggregate#getOrderedRecords() + */ + public int + getOrdinal() + { + return ordinal; + } + + /** + * Package level access; called by Aggregate + */ + void + setOrdinal(int n) + { + if (n < 0) { + throw new IllegalArgumentException("ordinal is negative"); + } + ordinal = n; + } + + /** * Compares the specified object with this aggregation record for * equality. Defines equality as having the same tuple and value. * diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Distribution.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Distribution.java index 6cab69c29d..30d606ebaf 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Distribution.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Distribution.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -235,15 +235,15 @@ public abstract class Distribution implements AggregationValue, } /** - * Gets a read-only {@code List} view of this ditribution. + * Gets a read-only {@code List} view of this distribution. * - * @return a read-only {@code List} view of this ditribution + * @return a read-only {@code List} view of this distribution */ public List <Bucket> asList() { checkInit(); - return Collections.unmodifiableList(buckets); + return Collections. <Bucket> unmodifiableList(buckets); } /** diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ExitRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ExitRecord.java index 7a046e555e..e14a1f26b4 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ExitRecord.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ExitRecord.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -47,7 +47,23 @@ public final class ExitRecord implements Record, Serializable { BeanInfo info = Introspector.getBeanInfo(ExitRecord.class); PersistenceDelegate persistenceDelegate = new DefaultPersistenceDelegate( - new String[] {"status"}); + new String[] {"status"}) + { + /* + * Need to prevent DefaultPersistenceDelegate from using + * overridden equals() method, resulting in a + * StackOverFlowError. Revert to PersistenceDelegate + * implementation. See + * http://forum.java.sun.com/thread.jspa?threadID= + * 477019&tstart=135 + */ + protected boolean + mutatesTo(Object oldInstance, Object newInstance) + { + return (newInstance != null && oldInstance != null && + oldInstance.getClass() == newInstance.getClass()); + } + }; BeanDescriptor d = info.getBeanDescriptor(); d.setValue("persistenceDelegate", persistenceDelegate); } catch (IntrospectionException e) { @@ -81,6 +97,36 @@ public final class ExitRecord implements Record, Serializable { } /** + * Compares the specified object with this {@code ExitRecord} for + * equality. Returns {@code true} if and only if the specified + * object is also an {@code ExitRecord} and both records have the + * same status. + * + * @return {@code true} if and only if the specified object is also + * an {@code ExitRecord} and both records have the same status + */ + @Override + public boolean + equals(Object o) + { + if (o instanceof ExitRecord) { + ExitRecord r = (ExitRecord)o; + return (status == r.status); + } + return false; + } + + /** + * Overridden to ensure that equal instances have equal hash codes. + */ + @Override + public int + hashCode() + { + return status; + } + + /** * Gets a string representation of the exit status. * * @return the string form of {@link #getStatus()} returned by diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java index 5bf2ae914a..a6be4af2a7 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -159,10 +159,10 @@ public final class KernelStackRecord implements StackValueRecord, KernelStackRecord(StackFrame[] frames, byte[] rawBytes) { if (frames != null) { - stackFrames = (StackFrame[])frames.clone(); + stackFrames = frames.clone(); } if (rawBytes != null) { - rawStackData = (byte[])rawBytes.clone(); + rawStackData = rawBytes.clone(); } validate(); } @@ -190,7 +190,7 @@ public final class KernelStackRecord implements StackValueRecord, if (stackFrames == null) { return EMPTY_FRAMES; } - return (StackFrame[])stackFrames.clone(); + return stackFrames.clone(); } /** @@ -219,7 +219,7 @@ public final class KernelStackRecord implements StackValueRecord, public byte[] getRawStackData() { - return (byte[])rawStackData.clone(); + return rawStackData.clone(); } /** @@ -232,7 +232,7 @@ public final class KernelStackRecord implements StackValueRecord, public Object getValue() { - return (byte[])rawStackData.clone(); + return rawStackData.clone(); } public List <StackFrame> @@ -241,7 +241,8 @@ public final class KernelStackRecord implements StackValueRecord, if (stackFrames == null) { return Collections. <StackFrame> emptyList(); } - return Collections.unmodifiableList(Arrays.asList(stackFrames)); + return Collections. <StackFrame> unmodifiableList( + Arrays.asList(stackFrames)); } /** @@ -313,10 +314,10 @@ public final class KernelStackRecord implements StackValueRecord, s.defaultReadObject(); // Make a defensive copy of stack frames and raw bytes if (stackFrames != null) { - stackFrames = (StackFrame[])stackFrames.clone(); + stackFrames = stackFrames.clone(); } if (rawStackData != null) { - rawStackData = (byte[])rawStackData.clone(); + rawStackData = rawStackData.clone(); } // check class invariants try { diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java index 930102f274..51e2630931 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -52,7 +52,7 @@ public class LocalConsumer implements Consumer { static Logger logger = Logger.getLogger(LocalConsumer.class.getName()); // Needs to match the version in dtrace_jni.c - private static final int DTRACE_JNI_VERSION = 2; + private static final int DTRACE_JNI_VERSION = 3; private static final Option[] DEFAULT_OPTIONS = new Option[] { new Option(Option.bufsize, Option.kb(256)), diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintaRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintaRecord.java index d30bf1d364..616a955223 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintaRecord.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintaRecord.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -75,7 +75,8 @@ import java.util.*; * * @author Tom Erickson */ -public final class PrintaRecord implements Record, Serializable { +public final class PrintaRecord implements Record, Serializable, + Comparable <PrintaRecord> { static final long serialVersionUID = -4174277639915895694L; static { @@ -84,7 +85,23 @@ public final class PrintaRecord implements Record, Serializable { PersistenceDelegate persistenceDelegate = new DefaultPersistenceDelegate( new String[] {"snaptime", "aggregations", - "formattedStrings", "tuples", "output"}); + "formattedStrings", "tuples", "output"}) + { + /* + * Need to prevent DefaultPersistenceDelegate from using + * overridden equals() method, resulting in a + * StackOverFlowError. Revert to PersistenceDelegate + * implementation. See + * http://forum.java.sun.com/thread.jspa?threadID= + * 477019&tstart=135 + */ + protected boolean + mutatesTo(Object oldInstance, Object newInstance) + { + return (newInstance != null && oldInstance != null && + oldInstance.getClass() == newInstance.getClass()); + } + }; BeanDescriptor d = info.getBeanDescriptor(); d.setValue("persistenceDelegate", persistenceDelegate); } catch (IntrospectionException e) { @@ -407,6 +424,68 @@ public final class PrintaRecord implements Record, Serializable { } /** + * Compares the specified object with this {@code PrintaRecord} for + * equality. Returns {@code true} if and only if the specified + * object is also a {@code PrintaRecord} and both records have the + * same aggregations and the same formatted strings in the same + * order (by aggregation tuple). + * + * @return {@code true} if and only if the specified object is also + * a {@code PrintaRecord} and both records have the same + * aggregations and the same formatted strings in the same order (by + * aggregation tuple) + */ + @Override + public boolean + equals(Object o) + { + if (o instanceof PrintaRecord) { + PrintaRecord r = (PrintaRecord)o; + return (aggregations.equals(r.aggregations) && + ((formattedStrings == null || formattedStrings.isEmpty()) + ? (r.formattedStrings == null || + r.formattedStrings.isEmpty()) + : formattedStrings.equals(r.formattedStrings)) && + tuples.equals(r.tuples)); + } + + return false; + } + + /** + * Overridden to ensure that equal instances have equal hash codes. + */ + @Override + public int + hashCode() + { + int hash = 17; + hash = (hash * 37) + aggregations.hashCode(); + hash = (hash * 37) + ((formattedStrings == null || + formattedStrings.isEmpty()) ? 0 : + formattedStrings.hashCode()); + hash = (hash * 37) + tuples.hashCode(); + return hash; + } + + /** + * Compares the formatted {@link #getOutput() output} of this record + * with that of the given record. Note that ordering {@code printa} + * records by their output string values is incompatible with {@link + * #equals(Object o) equals()}, which also checks the underlying + * aggregation data for equality. + * + * @return a negative number, 0, or a positive number as this + * record's formatted output is lexicographically less than, equal + * to, or greater than the given record's formatted output + */ + public int + compareTo(PrintaRecord r) + { + return getOutput().compareTo(r.getOutput()); + } + + /** * Serialize this {@code PrintaRecord} instance. * * @serialData Serialized fields are emitted, followed by the diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java index e1adbd989f..e2aee1bce7 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -38,7 +38,8 @@ import java.util.*; * * @author Tom Erickson */ -public final class PrintfRecord implements Record, Serializable { +public final class PrintfRecord implements Record, Serializable, + Comparable <PrintfRecord> { static final long serialVersionUID = 727237355963977675L; static { @@ -46,7 +47,23 @@ public final class PrintfRecord implements Record, Serializable { BeanInfo info = Introspector.getBeanInfo(PrintfRecord.class); PersistenceDelegate persistenceDelegate = new DefaultPersistenceDelegate( - new String[] {"records", "formattedString"}); + new String[] {"records", "formattedString"}) + { + /* + * Need to prevent DefaultPersistenceDelegate from using + * overridden equals() method, resulting in a + * StackOverFlowError. Revert to PersistenceDelegate + * implementation. See + * http://forum.java.sun.com/thread.jspa?threadID= + * 477019&tstart=135 + */ + protected boolean + mutatesTo(Object oldInstance, Object newInstance) + { + return (newInstance != null && oldInstance != null && + oldInstance.getClass() == newInstance.getClass()); + } + }; BeanDescriptor d = info.getBeanDescriptor(); d.setValue("persistenceDelegate", persistenceDelegate); } catch (IntrospectionException e) { @@ -150,7 +167,7 @@ public final class PrintfRecord implements Record, Serializable { public List <ValueRecord> getRecords() { - return Collections.unmodifiableList(records); + return Collections. <ValueRecord> unmodifiableList(records); } /** @@ -189,6 +206,58 @@ public final class PrintfRecord implements Record, Serializable { return records.get(i); } + /** + * Compares the specified object with this {@code PrintfRecord} for + * equality. Returns {@code true} if and only if the specified + * object is also a {@code PrintfRecord} and both records have the + * same formatted string and underlying data elements. + * + * @return {@code true} if and only if the specified object is also + * a {@code PrintfRecord} and both the formatted strings <i>and</i> + * the underlying data elements of both records are equal + */ + @Override + public boolean + equals(Object o) + { + if (o instanceof PrintfRecord) { + PrintfRecord r = (PrintfRecord)o; + return (records.equals(r.records) && + formattedString.equals(r.formattedString)); + } + return false; + } + + /** + * Overridden to ensure that equal instances have equal hash codes. + */ + @Override + public int + hashCode() + { + int hash = 17; + hash = (37 * hash) + records.hashCode(); + hash = (37 * hash) + formattedString.hashCode(); + return hash; + } + + /** + * Compares the formatted string value of this record with that of + * the given record. Note that ordering {@code printf} records by + * their string values is incompatible with {@link #equals(Object o) + * equals()}, which also checks the underlying data elements for + * equality. + * + * @return a negative number, 0, or a positive number as this + * record's formatted string is lexicographically less than, equal + * to, or greater than the given record's formatted string + */ + public int + compareTo(PrintfRecord r) + { + return formattedString.compareTo(r.formattedString); + } + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java index cdcfa52f71..a579ade0e1 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -730,7 +730,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> { public List <Record> getRecords() { - return Collections.unmodifiableList(records); + return Collections. <Record> unmodifiableList(records); } /** diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Program.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Program.java index 1d5863d4a7..72dc4f888e 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Program.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Program.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -213,6 +213,8 @@ public class Program implements Serializable { * compiled from a file. */ public static final class File extends Program { + static final long serialVersionUID = 6217493430514165300L; + // Set by LocalConsumer.compile() /** @serial */ java.io.File file; diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/StddevValue.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/StddevValue.java new file mode 100644 index 0000000000..c845edcdf3 --- /dev/null +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/StddevValue.java @@ -0,0 +1,268 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ +package org.opensolaris.os.dtrace; + +import java.io.*; +import java.beans.*; +import java.math.BigInteger; + +/** + * A {@code long} value aggregated by the DTrace {@code stddev()} action. + * <p> + * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. + * + * @see Aggregation + * @author Tom Erickson + */ +public final class StddevValue extends AbstractAggregationValue { + static final long serialVersionUID = 6409878160513885375L; + + /** @serial */ + private final long total; + /** @serial */ + private final long count; + /** @serial */ + private final BigInteger totalSquares; + + static { + try { + BeanInfo info = Introspector.getBeanInfo(StddevValue.class); + PersistenceDelegate persistenceDelegate = + new DefaultPersistenceDelegate( + new String[] {"value", "total", "count", "totalSquares"}) + { + @Override + protected Expression + instantiate(Object oldInstance, Encoder out) + { + StddevValue stddev = (StddevValue)oldInstance; + return new Expression(oldInstance, oldInstance.getClass(), + "new", new Object[] { + stddev.getValue().longValue(), + stddev.getTotal(), stddev.getCount(), + stddev.getTotalSquares().toString() }); + } + }; + BeanDescriptor d = info.getBeanDescriptor(); + d.setValue("persistenceDelegate", persistenceDelegate); + } catch (IntrospectionException e) { + System.out.println(e); + } + } + + // ported from dt_sqrt_128 in lib/libdtrace/common/dt_consume.c + private static long + squareRoot128(BigInteger n) + { + long result = 0; + BigInteger diff = BigInteger.valueOf(0); + BigInteger nextTry = BigInteger.valueOf(0); + int bitPairs = (n.bitLength() / 2); + int bitPos = (bitPairs * 2) + 1; + int nextTwoBits; + + for (int i = 0; i <= bitPairs; i++) { + // Bring down the next pair of bits. + nextTwoBits = n.testBit(bitPos) + ? (n.testBit(bitPos - 1) ? 0x3 : 0x2) + : (n.testBit(bitPos - 1) ? 0x1 : 0x0); + + diff = diff.shiftLeft(2); + diff = diff.add(BigInteger.valueOf(nextTwoBits)); + + // nextTry = R << 2 + 1 + nextTry = BigInteger.valueOf(result); + nextTry = nextTry.shiftLeft(2); + nextTry = nextTry.setBit(0); + + result <<= 1; + if (nextTry.compareTo(diff) <= 0) { + diff = diff.subtract(nextTry); + result++; + } + + bitPos -= 2; + } + + return (result); + } + + // ported from dt_stddev in lib/libdtrace/common/dt_consume.c + private static long + standardDeviation(long stddevCount, long stddevTotal, + BigInteger stddevTotalSquares) + { + BigInteger averageOfSquares = stddevTotalSquares.divide( + BigInteger.valueOf(stddevCount)); + long avg = (stddevTotal / stddevCount); + if (avg < 0) { + avg = -avg; + } + BigInteger squareOfAverage = BigInteger.valueOf(avg); + squareOfAverage = squareOfAverage.pow(2); + BigInteger stddev = averageOfSquares.subtract(squareOfAverage); + return squareRoot128(stddev); + } + + /* + * Called by native code. + */ + private + StddevValue(long stddevCount, long stddevTotal, + BigInteger stddevTotalSquares) + { + super(stddevCount == 0 ? 0 : standardDeviation(stddevCount, + stddevTotal, stddevTotalSquares)); + total = stddevTotal; + count = stddevCount; + totalSquares = stddevTotalSquares; + if (totalSquares == null) { + throw new NullPointerException("totalSquares is null"); + } + if (count < 0) { + throw new IllegalArgumentException("count is negative"); + } + } + + /** + * Creates a value aggregated by the DTrace {@code stddev()} action. + * Supports XML persistence. + * + * @param v standard deviation + * @param stddevTotal sum total of all values included in the standard + * deviation + * @param stddevCount number of values included in the standard + * deviation + * @param stddevTotalSquaresString decimal string representation of + * the 128-bit sum total of the squares of all values included in + * the standard deviation + * @throws IllegalArgumentException if the given count is negative + * or if the given standard deviation is not the value expected for + * the given total, total of squares, and count + * @throws NumberFormatException if the given total squares is not a + * valid integer representation + */ + public + StddevValue(long v, long stddevTotal, long stddevCount, + String stddevTotalSquaresString) + { + super(v); + total = stddevTotal; + count = stddevCount; + totalSquares = new BigInteger(stddevTotalSquaresString); + validate(); + } + + private final void + validate() + { + if (count < 0) { + throw new IllegalArgumentException("count is negative"); + } + long stddev = super.getValue().longValue(); + if (count == 0) { + if (stddev != 0) { + throw new IllegalArgumentException( + "count of values is zero, stddev is non-zero (" + + stddev + ")"); + } + } else { + if (stddev != standardDeviation(count, total, totalSquares)) { + throw new IllegalArgumentException( + getValue().toString() + " is not the expected " + + "standard deviation of total " + total + ", count " + + count + ", and total squares " + totalSquares); + } + } + } + + // Needed to support XML persistence since XMLDecoder cannot find + // the public method of the non-public superclass. + + /** + * Gets the standard deviation of the aggregated values. + * + * @return standard deviation of the aggregated values + */ + public Long + getValue() + { + return (Long)super.getValue(); + } + + /** + * Gets the sum total of the aggregated values. + * + * @return the sum total of the aggregated values + */ + public long + getTotal() + { + return total; + } + + /** + * Gets the number of aggregated values included in the standard + * deviation. + * + * @return the number of aggregated values included in the standard + * deviation + */ + public long + getCount() + { + return count; + } + + /** + * Gets the sum total of the squares of the aggregated values. + * + * @return the sum total of the squares of the aggregated values + */ + public BigInteger + getTotalSquares() + { + return totalSquares; + } + + private void + readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + // check invariants + try { + validate(); + } catch (Exception e) { + InvalidObjectException x = new InvalidObjectException( + e.getMessage()); + x.initCause(e); + throw x; + } + } +} diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java index 6959c1eadb..03d1305e2f 100644 --- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java +++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" @@ -186,7 +186,7 @@ public final class Tuple implements Serializable, Comparable <Tuple>, public List <ValueRecord> asList() { - return Collections.unmodifiableList(elements); + return Collections. <ValueRecord> unmodifiableList(elements); } /** |