940 llquantize() dreams of JNI
authorRichard Lowe <richlowe@richlowe.net>
Wed, 20 Apr 2011 01:14:34 -0400
changeset 13357 af2b8df56c61
parent 13356 ae254853587f
child 13358 f7ba8ec46a21
940 llquantize() dreams of JNI Reviewed by: Albert Lee <[email protected]> Reviewed by: Gordon Ross <[email protected]> Approved by: Garrett D'Amore <[email protected]>
usr/src/cmd/dtrace/test/cmd/jdtrace/JDTrace.java
usr/src/cmd/dtrace/test/tst/common/java_api/src/TestBean.java
usr/src/cmd/dtrace/test/tst/common/java_api/tst.Bean.ksh.out
usr/src/lib/libdtrace_jni/common/dtj_consume.c
usr/src/lib/libdtrace_jni/common/dtj_jnitab.c
usr/src/lib/libdtrace_jni/common/dtrace_jni.h
usr/src/lib/libdtrace_jni/java/Makefile
usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LogLinearDistribution.java
usr/src/pkg/manifests/developer-dtrace.mf
--- a/usr/src/cmd/dtrace/test/cmd/jdtrace/JDTrace.java	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/cmd/dtrace/test/cmd/jdtrace/JDTrace.java	Wed Apr 20 01:14:34 2011 -0400
@@ -23,7 +23,6 @@
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
- * ident	"%Z%%M%	%I%	%E% SMI"
  */
 import org.opensolaris.os.dtrace.*;
 import java.io.*;
@@ -303,6 +302,7 @@
 	Distribution.Bucket bucket;
 	int b1 = 0; // first displayed bucket
 	int b2 = d.size() - 1; // last displayed bucket
+
 	for (; (b1 <= b2) && (d.get(b1).getFrequency() == 0); ++b1);
 	// If possible, get one bucket before the first non-zero
 	// bucket and one bucket after the last.
@@ -337,9 +337,14 @@
 	    v = bucket.getFrequency();
 	    b = bucket.getMin();
 
-	    if (d instanceof LinearDistribution) {
+	    if ((d instanceof LinearDistribution) ||
+		(d instanceof LogLinearDistribution)) {
 		if (b == Long.MIN_VALUE) {
-		    String lt = "< " + ((LinearDistribution)d).getBase();
+		    String lt;
+		    if (d instanceof LinearDistribution)
+			lt = "< " + ((LinearDistribution)d).getBase();
+		    else
+			lt = "< " + ((LogLinearDistribution)d).getBase();
 		    out.printf("%16s ", lt);
 		} else if (bucket.getMax() == Long.MAX_VALUE) {
 		    String ge = ">= " + b;
--- a/usr/src/cmd/dtrace/test/tst/common/java_api/src/TestBean.java	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/cmd/dtrace/test/tst/common/java_api/src/TestBean.java	Wed Apr 20 01:14:34 2011 -0400
@@ -22,8 +22,6 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- *
- * ident	"%Z%%M%	%I%	%E% SMI"
  */
 
 import org.opensolaris.os.dtrace.*;
@@ -50,6 +48,7 @@
 	"KernelStackRecord",
 	"LogDistribution",
 	"LinearDistribution",
+	"LogLinearDistribution",
 	"Option",
 	"ProcessState",
 	"ProbeDescription",
@@ -264,6 +263,50 @@
 	return d;
     }
 
+    public static LogLinearDistribution
+    getLogLinearDistribution()
+    {
+        Distribution.Bucket bucket;
+        long next, step;
+        long low = 0;
+        long high = 6;
+        long factor = 2;
+        long nsteps = 2;
+        int value = 1;
+        int order;
+
+        List < Distribution.Bucket > buckets =
+          new ArrayList < Distribution.Bucket > ();
+
+        for (order = 0; order < low; order++)
+            value *= factor;
+
+        bucket = new Distribution.Bucket(Long.MIN_VALUE, (value - 1), 0);
+        buckets.add(bucket);
+
+        next = value * factor;
+        step = (next > nsteps) ? (next / nsteps) : 1;
+
+        while (order <= high) {
+            bucket = new Distribution.Bucket(value, value + step - 1, 5);
+            buckets.add(bucket);
+
+            if ((value += step) != next)
+                continue;
+
+            next = value * factor;
+            step = (next > nsteps) ? (next / nsteps) : 1;
+            order++;
+        }
+
+        bucket = new Distribution.Bucket(value, Long.MAX_VALUE, 0);
+        buckets.add(bucket);
+
+        LogLinearDistribution d = new LogLinearDistribution(factor, low, high,
+          nsteps, 0, buckets);
+        return d;
+    }
+
     public static Option
     getOption()
     {
--- a/usr/src/cmd/dtrace/test/tst/common/java_api/tst.Bean.ksh.out	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/cmd/dtrace/test/tst/common/java_api/tst.Bean.ksh.out	Wed Apr 20 01:14:34 2011 -0400
@@ -158,6 +158,12 @@
 LinearDistribution:
   encoded: class org.opensolaris.os.dtrace.LinearDistribution[base = 1, step = 10, buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 10, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 11, max = 20, frequency = 1], org.opensolaris.os.dtrace.Distribution$Bucket[min = 21, max = 30, frequency = 2], org.opensolaris.os.dtrace.Distribution$Bucket[min = 31, max = 40, frequency = 3], org.opensolaris.os.dtrace.Distribution$Bucket[min = 41, max = 50, frequency = 4], org.opensolaris.os.dtrace.Distribution$Bucket[min = 51, max = 60, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 61, max = 70, frequency = 6], org.opensolaris.os.dtrace.Distribution$Bucket[min = 71, max = 80, frequency = 7], org.opensolaris.os.dtrace.Distribution$Bucket[min = 81, max = 90, frequency = 8], org.opensolaris.os.dtrace.Distribution$Bucket[min = 91, max = 100, frequency = 9], org.opensolaris.os.dtrace.Distribution$Bucket[min = 101, max = 9223372036854775807, frequency = 0]], total = 45.0]
   decoded: class org.opensolaris.os.dtrace.LinearDistribution[base = 1, step = 10, buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 10, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 11, max = 20, frequency = 1], org.opensolaris.os.dtrace.Distribution$Bucket[min = 21, max = 30, frequency = 2], org.opensolaris.os.dtrace.Distribution$Bucket[min = 31, max = 40, frequency = 3], org.opensolaris.os.dtrace.Distribution$Bucket[min = 41, max = 50, frequency = 4], org.opensolaris.os.dtrace.Distribution$Bucket[min = 51, max = 60, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 61, max = 70, frequency = 6], org.opensolaris.os.dtrace.Distribution$Bucket[min = 71, max = 80, frequency = 7], org.opensolaris.os.dtrace.Distribution$Bucket[min = 81, max = 90, frequency = 8], org.opensolaris.os.dtrace.Distribution$Bucket[min = 91, max = 100, frequency = 9], org.opensolaris.os.dtrace.Distribution$Bucket[min = 101, max = 9223372036854775807, frequency = 0]], total = 45.0]
+LogLinearDistribution:
+  serialized: org.opensolaris.os.dtrace.Distribution[buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = -9223372036854775808, max = 0, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 1, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 2, max = 3, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 4, max = 7, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 8, max = 15, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 16, max = 31, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 32, max = 63, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 64, max = 127, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 128, max = 9223372036854775807, frequency = 0]], total = 35.0]
+  deserialized: org.opensolaris.os.dtrace.Distribution[buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = -9223372036854775808, max = 0, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 1, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 2, max = 3, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 4, max = 7, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 8, max = 15, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 16, max = 31, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 32, max = 63, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 64, max = 127, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 128, max = 9223372036854775807, frequency = 0]], total = 35.0]
+LogLinearDistribution:
+  encoded: org.opensolaris.os.dtrace.Distribution[buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = -9223372036854775808, max = 0, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 1, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 2, max = 3, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 4, max = 7, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 8, max = 15, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 16, max = 31, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 32, max = 63, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 64, max = 127, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 128, max = 9223372036854775807, frequency = 0]], total = 35.0]
+  decoded: org.opensolaris.os.dtrace.Distribution[buckets = [org.opensolaris.os.dtrace.Distribution$Bucket[min = -9223372036854775808, max = 0, frequency = 0], org.opensolaris.os.dtrace.Distribution$Bucket[min = 1, max = 1, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 2, max = 3, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 4, max = 7, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 8, max = 15, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 16, max = 31, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 32, max = 63, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 64, max = 127, frequency = 5], org.opensolaris.os.dtrace.Distribution$Bucket[min = 128, max = 9223372036854775807, frequency = 0]], total = 35.0]
 Option:
   serialized: org.opensolaris.os.dtrace.Option[name = aggrate, value = 1s]
   deserialized: org.opensolaris.os.dtrace.Option[name = aggrate, value = 1s]
--- a/usr/src/lib/libdtrace_jni/common/dtj_consume.c	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/lib/libdtrace_jni/common/dtj_consume.c	Wed Apr 20 01:14:34 2011 -0400
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdio.h>
 #include <ctype.h>
 #include <limits.h>
@@ -1531,7 +1529,8 @@
 	int n; /* number of buckets */
 
 	/* distribution */
-	if (act == DTRACEAGG_LQUANTIZE) {
+	switch (act) {
+	case DTRACEAGG_LQUANTIZE:
 		/* first "bucket" used for range and step */
 		value = *aggbuckets++;
 		base = DTRACE_LQUANTIZE_BASE(value);
@@ -1543,10 +1542,19 @@
 		 * less than the base.
 		 */
 		n = levels + 2;
-	} else {
+		break;
+	case DTRACEAGG_LLQUANTIZE:
+		value = *aggbuckets++;
+		size -= sizeof (int64_t);
+		levels = size / sizeof (int64_t);
+		n = levels;
+		break;
+	case DTRACEAGG_QUANTIZE:
 		n = DTRACE_QUANTIZE_NBUCKETS;
 		levels = n - 1; /* levels excludes base */
+		break;
 	}
+
 	if (size != (n * sizeof (uint64_t)) || n < 1) {
 		dtj_throw_illegal_state(jenv,
 		    "size mismatch: record %d, buckets %d", size,
@@ -1559,6 +1567,7 @@
 	if (!jbuckets) {
 		return (NULL); /* exception pending */
 	}
+
 	if (n > 0) {
 		(*jenv)->SetLongArrayRegion(jenv, jbuckets, 0, n, aggbuckets);
 		/* check for ArrayIndexOutOfBounds */
@@ -1569,13 +1578,20 @@
 		}
 	}
 
-	if (act == DTRACEAGG_LQUANTIZE) {
+	switch (act) {
+	case DTRACEAGG_LQUANTIZE:
 		/* Must pass 64-bit base and step or constructor gets junk. */
 		jdist = (*jenv)->NewObject(jenv, g_ldist_jc, g_ldistinit_jm,
 		    base, step, jbuckets);
-	} else {
+		break;
+	case DTRACEAGG_QUANTIZE:
 		jdist = (*jenv)->NewObject(jenv, g_dist_jc, g_distinit_jm,
 		    jbuckets);
+		break;
+	case DTRACEAGG_LLQUANTIZE:
+		jdist = (*jenv)->NewObject(jenv, g_lldist_jc, g_lldistinit_jm,
+		    value, jbuckets);
+		break;
 	}
 
 	(*jenv)->DeleteLocalRef(jenv, jbuckets);
@@ -2009,7 +2025,8 @@
 		value = (*((int64_t *)addr)) / normal;
 	}
 
-	if (act == DTRACEAGG_QUANTIZE || act == DTRACEAGG_LQUANTIZE) {
+	if ((act == DTRACEAGG_QUANTIZE) || (act == DTRACEAGG_LQUANTIZE) ||
+	    (act == DTRACEAGG_LLQUANTIZE)) {
 		jvalue = dtj_new_distribution(data, rec, jc);
 	} else {
 		switch (act) {
--- a/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c	Wed Apr 20 01:14:34 2011 -0400
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdlib.h>
 #include <stddef.h>
 #include <limits.h>
@@ -198,6 +196,10 @@
 jclass g_dist_jc = 0;
 jmethodID g_distinit_jm = 0;
 
+/* LogLinear Distribution */
+jclass g_lldist_jc = 0;
+jmethodID g_lldistinit_jm = 0;
+
 /* LinearDistribution */
 jclass g_ldist_jc = 0;
 jmethodID g_ldistinit_jm = 0;
@@ -451,6 +453,11 @@
 			"org/opensolaris/os/dtrace/LogDistribution" },
 		{ JMETHOD,  &g_distinit_jm, CONSTRUCTOR, "([J)V" },
 
+		/* LogLinearDistribution */
+		{ JCLASS, &g_lldist_jc,
+			"org/opensolaris/os/dtrace/LogLinearDistribution" },
+		{ JMETHOD, &g_lldistinit_jm, CONSTRUCTOR, "(J[J)V" },
+
 		/* LinearDistribution */
 		{ JCLASS,  &g_ldist_jc,
 			"org/opensolaris/os/dtrace/LinearDistribution" },
--- a/usr/src/lib/libdtrace_jni/common/dtrace_jni.h	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/lib/libdtrace_jni/common/dtrace_jni.h	Wed Apr 20 01:14:34 2011 -0400
@@ -27,8 +27,6 @@
 #ifndef	_DTRACE_JNI_H
 #define	_DTRACE_JNI_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <libuutil.h>
 #include <jni.h>
 #include <dtrace.h>
@@ -402,6 +400,10 @@
 extern jclass g_dist_jc;
 extern jmethodID g_distinit_jm;
 
+/* LogLinearDistribution */
+extern jclass g_lldist_jc;
+extern jmethodID g_lldistinit_jm;
+
 /* LinearDistribution */
 extern jclass g_ldist_jc;
 extern jmethodID g_ldistinit_jm;
--- a/usr/src/lib/libdtrace_jni/java/Makefile	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/lib/libdtrace_jni/java/Makefile	Wed Apr 20 01:14:34 2011 -0400
@@ -23,8 +23,6 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 
 include $(SRC)/Makefile.master
 
@@ -131,6 +129,7 @@
 	LinearDistribution \
 	LocalConsumer \
 	LogDistribution \
+	LogLinearDistribution \
 	MaxValue \
 	MinValue \
 	NativeException \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LogLinearDistribution.java	Wed Apr 20 01:14:34 2011 -0400
@@ -0,0 +1,241 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2011, Richard Lowe
+ */
+
+package org.opensolaris.os.dtrace;
+
+import java.beans.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * A log/linear distribution aggregated by the DTrace {@code llquantize()}
+ * action.  Aggregated values are aggregated logarithmicly by order of
+ * magnitude (between the low and high magnitude arguments of the {@code
+ * llquantize()} action, but linearly within each order of magnitude bounded
+ * by the step parameter of the {@code llquantize()} action.
+ *
+ * @see LinearDistribution
+ * @see LogLinearDistribution
+ * @see Aggregation
+ */
+public final class LogLinearDistribution extends Distribution
+    implements Serializable, Comparable <LogLinearDistribution>
+{
+    static final long serialVersionUID = 6271156690706677711L;
+
+    static final long UINT16_MAX = 0xffff;
+
+    static final long FACTOR_SHIFT = 48;
+    static final long LOW_SHIFT = 32;
+    static final long HIGH_SHIFT = 16;
+    static final long NSTEP_SHIFT = 0;
+
+    private static long unpack(long x, long thing) {
+        return (x & (UINT16_MAX << thing)) >> thing;
+    }
+
+    /** @serial */
+    private long encValue;
+    /** @serial */
+    private long base;
+
+    static {
+        try {
+            BeanInfo info = Introspector.getBeanInfo(
+                LogLinearDistribution.class);
+            PersistenceDelegate persistenceDelegate =
+              new DefaultPersistenceDelegate(
+                  new String[] { "encValue", "base", "buckets" });
+            BeanDescriptor d = info.getBeanDescriptor();
+            d.setValue("persistenceDelegate", persistenceDelegate);
+        } catch (IntrospectionException e) {
+            System.out.println(e);
+        }
+    }
+
+    /**
+     * Called by the native C code
+     */
+    private LogLinearDistribution(long constant, long[] frequencies) {
+        super(0, constant, frequencies);
+        encValue = constant;
+    }
+
+
+    /**
+     * Creates a log/linear distribution with the given parameters, base value
+     * and frequencies.  Used by XML Persistence.
+     *
+     * @param enc The encoded representation of the high, low, step and steps
+     *  {@code llquantize()} paramaters.
+     * @param base The base value of the distirbution
+     * @param frequencies list of frequencies in each bucket range
+     */
+    public LogLinearDistribution(long enc, long base,
+        List<Bucket> frequencies) {
+        super(frequencies);
+
+        encValue = enc;
+        base = base;
+
+        initialize();
+    }
+
+    /**
+     * Creates a log/linear distribution with the given parameters, base
+     * values and frequencies.
+     *
+     * @param scaleFactor factor
+     * @param lowMagnitude the low magnitude
+     * @param highMagnitude the high magnitude
+     * @param bucketSteps number of linear steps per magnitude
+     * @param baseVal basue value
+     * @param frequencies list of frequencies in each bucket range
+     */
+    public LogLinearDistribution(long scaleFactor, long lowMagnitude,
+        long highMagnitude, long bucketSteps, long baseVal,
+        List<Bucket> frequencies) {
+
+        super(frequencies);
+
+        encValue = (scaleFactor << FACTOR_SHIFT) | (lowMagnitude << LOW_SHIFT) |
+          (highMagnitude << HIGH_SHIFT) | (bucketSteps << NSTEP_SHIFT);
+        base = baseVal;
+
+        initialize();
+    }
+
+    private long[][] rangeCache = null;
+
+    private void fillRangeCache(long constant, int len) {
+        long value = 1;
+        long next, step;
+        long low, high, nsteps, factor;
+        int order, bucket = 0;
+
+        low = unpack(constant, LOW_SHIFT);
+        high = unpack(constant, HIGH_SHIFT);
+        nsteps = unpack(constant, NSTEP_SHIFT);
+        factor = unpack(constant, FACTOR_SHIFT);
+
+        if (rangeCache == null)
+            rangeCache = new long[len][2];
+
+        for (order = 0; order < low; order++)
+            value *= factor;
+
+        base = value;
+
+        rangeCache[bucket][0] = Long.MIN_VALUE;
+        rangeCache[bucket][1] = value - 1;
+        bucket++;
+
+        next = value * factor;
+        step = (next > nsteps) ? (next / nsteps) : 1;
+
+        while (order <= high) {
+            rangeCache[bucket][0] = value;
+            rangeCache[bucket][1] = value + step - 1;
+            bucket++;
+
+            if ((value += step) != next)
+                continue;
+
+            next = value * factor;
+            step = (next > nsteps) ? (next / nsteps) : 1;
+            order++;
+        }
+
+        rangeCache[bucket][0] = value;
+        rangeCache[bucket][1] = Long.MAX_VALUE;
+    }
+
+    /**
+     * Gets a two element array: the first element is the range minimum
+     * (inclusive), the second element is the range maximum (inclusive).
+     */
+    @Override
+    long[] getBucketRange(int i, int len, long base, long constant) {
+        if (rangeCache == null)
+            fillRangeCache(constant, len);
+
+        return rangeCache[i];
+    }
+
+    @Override
+    long[] getBucketRange(int i, int len) {
+        return getBucketRange(i, len, 0, encValue);
+    }
+
+    public Number getValue() {
+        double total = 0;
+
+        List<Distribution.Bucket> buckets = getBuckets();
+        for (Distribution.Bucket bucket : buckets)
+            total += ((double)bucket.getFrequency() * (double)bucket.getMin());
+
+        return (new Double(total));
+    }
+
+    private long getZeroBucketValue() {
+        for (Distribution.Bucket b : this) {
+            if (b.getMin() == 0) {
+                return b.getFrequency();
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Compares the {@code double} values of {@link #getValue()} for overall
+     * magnitude, and if those are equal, compares frequencies at zero if the
+     * distrubions includea bucket whose range has a minimum of zero.
+     */
+    public int compareTo(LogLinearDistribution d) {
+        Number v1 = getValue();
+        Number v2 = getValue();
+        double d1 = v1.doubleValue();
+        double d2 = v2.doubleValue();
+        int cmp = (d1 < d2 ? -1 : (d1 > d2 ? 1 : 0));
+
+        if (cmp == 0) {
+            long z1 = getZeroBucketValue();
+            long z2 = d.getZeroBucketValue();
+            cmp = (z1 < z2 ? -1 : (z1 > z2 ? 1 : 0));
+        }
+        return (cmp);
+    }
+
+    public long getBase() {
+        return base;
+    }
+
+    public long getEncValue() {
+        return encValue;
+    }
+
+    private void readObject(ObjectInputStream s)
+        throws IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        try {
+            initialize();
+        } catch (Exception e) {
+            InvalidObjectException x = new InvalidObjectException(
+                e.getMessage());
+            x.initCause(e);
+            throw x;
+        }
+    }
+}
--- a/usr/src/pkg/manifests/developer-dtrace.mf	Wed Mar 09 23:33:10 2011 -0800
+++ b/usr/src/pkg/manifests/developer-dtrace.mf	Wed Apr 20 01:14:34 2011 -0400
@@ -325,6 +325,9 @@
     path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/LogDistribution.html \
     group=other
 file \
+    path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/LogLinearDistribution.html \
+    group=other
+file \
     path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/MaxValue.html \
     group=other
 file \
@@ -511,6 +514,9 @@
     path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/LogDistribution.html \
     group=other
 file \
+    path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/LogLinearDistribution.html \
+    group=other
+file \
     path=usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/MaxValue.html \
     group=other
 file \