1fb3fb4f3Stomee /*
2fb3fb4f3Stomee  * CDDL HEADER START
3fb3fb4f3Stomee  *
4fb3fb4f3Stomee  * The contents of this file are subject to the terms of the
5fb3fb4f3Stomee  * Common Development and Distribution License (the "License").
6fb3fb4f3Stomee  * You may not use this file except in compliance with the License.
7fb3fb4f3Stomee  *
8fb3fb4f3Stomee  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fb3fb4f3Stomee  * or http://www.opensolaris.org/os/licensing.
10fb3fb4f3Stomee  * See the License for the specific language governing permissions
11fb3fb4f3Stomee  * and limitations under the License.
12fb3fb4f3Stomee  *
13fb3fb4f3Stomee  * When distributing Covered Code, include this CDDL HEADER in each
14fb3fb4f3Stomee  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fb3fb4f3Stomee  * If applicable, add the following below this CDDL HEADER, with the
16fb3fb4f3Stomee  * fields enclosed by brackets "[]" replaced with your own identifying
17fb3fb4f3Stomee  * information: Portions Copyright [yyyy] [name of copyright owner]
18fb3fb4f3Stomee  *
19fb3fb4f3Stomee  * CDDL HEADER END
20fb3fb4f3Stomee  */
21fb3fb4f3Stomee 
22fb3fb4f3Stomee /*
2391cfa10aStomee  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24fb3fb4f3Stomee  * Use is subject to license terms.
25fb3fb4f3Stomee  *
26fb3fb4f3Stomee  * ident	"%Z%%M%	%I%	%E% SMI"
27fb3fb4f3Stomee  */
28fb3fb4f3Stomee package org.opensolaris.os.dtrace;
29fb3fb4f3Stomee 
30fb3fb4f3Stomee import java.util.*;
31fb3fb4f3Stomee import java.io.*;
32fb3fb4f3Stomee import java.beans.*;
33fb3fb4f3Stomee 
34fb3fb4f3Stomee /**
35fb3fb4f3Stomee  * A power-of-two logarithmic frequency distribution aggregated by the
36fb3fb4f3Stomee  * DTrace {@code quantize()} action.  Aggregated values fall into
37fb3fb4f3Stomee  * consecutive ranges, each twice as large as the previous range.  Each
38fb3fb4f3Stomee  * range, known as a bucket, begins at two to the power of <i>n</i> and
39fb3fb4f3Stomee  * ends at one less than the beginning of the next bucket, two to the
40fb3fb4f3Stomee  * power of <i>n + 1</i>.  The zero bucket is the degenerate case and
41fb3fb4f3Stomee  * holds the frequency of the base value zero.  For example, the first
42fb3fb4f3Stomee  * bucket after 0 starts at 1 (2 to the power of 0) and ends at 1 (one
43fb3fb4f3Stomee  * less than 2 to the power of 1).  The next bucket starts at 2 (2 to
44fb3fb4f3Stomee  * the power of 1) and ends at 3 (one less than 2 to the power of 2).
45fb3fb4f3Stomee  * Each bucket frequency is incremented for each aggregated value that
46fb3fb4f3Stomee  * falls into its range.  Buckets are typically identified by their
47fb3fb4f3Stomee  * lower bound: 1, 2, 4, 8, etc.  Mirroring these are buckets with
48fb3fb4f3Stomee  * negative ranges: -1, -2, -4, -8, etc.  The range of an entire {@code
49fb3fb4f3Stomee  * LogDistribution} is (<code>-2<sup>63</sup> ..
50fb3fb4f3Stomee  * 2<sup>63</sup></code>).
51fb3fb4f3Stomee  * <p>
52fb3fb4f3Stomee  * Immutable.  Supports persistence using {@link java.beans.XMLEncoder}.
53fb3fb4f3Stomee  *
54fb3fb4f3Stomee  * @see LinearDistribution
55fb3fb4f3Stomee  * @see Aggregation
56fb3fb4f3Stomee  *
57fb3fb4f3Stomee  * @author Tom Erickson
58fb3fb4f3Stomee  */
59fb3fb4f3Stomee public final class LogDistribution extends Distribution
60fb3fb4f3Stomee         implements Serializable, Comparable <LogDistribution>
61fb3fb4f3Stomee {
62fb3fb4f3Stomee     static final long serialVersionUID = -1279719751212721961L;
63fb3fb4f3Stomee 
64fb3fb4f3Stomee     static final int ZERO_BUCKET_INDEX = 63;
65fb3fb4f3Stomee 
66fb3fb4f3Stomee     static {
67fb3fb4f3Stomee 	try {
68fb3fb4f3Stomee 	    BeanInfo info = Introspector.getBeanInfo(LogDistribution.class);
69fb3fb4f3Stomee 	    PersistenceDelegate persistenceDelegate =
70fb3fb4f3Stomee 		    new DefaultPersistenceDelegate(
71fb3fb4f3Stomee 		    new String[] {"buckets"});
72fb3fb4f3Stomee 	    BeanDescriptor d = info.getBeanDescriptor();
73fb3fb4f3Stomee 	    d.setValue("persistenceDelegate", persistenceDelegate);
74fb3fb4f3Stomee 	} catch (IntrospectionException e) {
75fb3fb4f3Stomee 	    System.out.println(e);
76fb3fb4f3Stomee 	}
77fb3fb4f3Stomee     }
78fb3fb4f3Stomee 
79fb3fb4f3Stomee     /**
80fb3fb4f3Stomee      * Called by native C code
81fb3fb4f3Stomee      */
82fb3fb4f3Stomee     private
LogDistribution(long[] buckets)83fb3fb4f3Stomee     LogDistribution(long[] buckets)
84fb3fb4f3Stomee     {
85fb3fb4f3Stomee 	super(0, 2, buckets); // initializes using base 0, power of 2
86fb3fb4f3Stomee     }
87fb3fb4f3Stomee 
88fb3fb4f3Stomee     /**
89fb3fb4f3Stomee      * Creates a logarithmic distribution with the given frequencies.
90fb3fb4f3Stomee      * Supports XML persistence.
91fb3fb4f3Stomee      *
92fb3fb4f3Stomee      * @param frequencies list of frequencies in bucket ranges bounded
93fb3fb4f3Stomee      * by consucutive powers of two
94fb3fb4f3Stomee      * @throws NullPointerException if {@code frequencies} is {@code
95fb3fb4f3Stomee      * null}
96fb3fb4f3Stomee      * @throws IllegalArgumentException if any bucket does not have the
97fb3fb4f3Stomee      * expected range (bounded by consecutive powers of two)
98fb3fb4f3Stomee      */
99fb3fb4f3Stomee     public
LogDistribution(List <Bucket> frequencies)100fb3fb4f3Stomee     LogDistribution(List <Bucket> frequencies)
101fb3fb4f3Stomee     {
102fb3fb4f3Stomee 	super(frequencies);
103fb3fb4f3Stomee 	initialize();
104fb3fb4f3Stomee     }
105fb3fb4f3Stomee 
106fb3fb4f3Stomee     /**
107fb3fb4f3Stomee      * Gets a two element array: the first elelemt is the range minimum
108fb3fb4f3Stomee      * (inclusive), the second element is the range maximum (inclusive).
109fb3fb4f3Stomee      */
110fb3fb4f3Stomee     @Override
111fb3fb4f3Stomee     long[]
getBucketRange(int i, int len, long base, long constant)112fb3fb4f3Stomee     getBucketRange(int i, int len, long base, long constant)
113fb3fb4f3Stomee     {
114fb3fb4f3Stomee 	long min = LocalConsumer._quantizeBucket(i);
115fb3fb4f3Stomee 	long max = (LocalConsumer._quantizeBucket(i + 1) - 1);
116fb3fb4f3Stomee 
117fb3fb4f3Stomee 	long[] range = new long[] {min, max};
118fb3fb4f3Stomee 	return range;
119fb3fb4f3Stomee     }
120fb3fb4f3Stomee 
121fb3fb4f3Stomee     @Override
122fb3fb4f3Stomee     long[]
getBucketRange(int i, int len)123fb3fb4f3Stomee     getBucketRange(int i, int len)
124fb3fb4f3Stomee     {
125fb3fb4f3Stomee 	return getBucketRange(i, len, 0, 2);
126fb3fb4f3Stomee     }
127fb3fb4f3Stomee 
128fb3fb4f3Stomee     public Number
getValue()129fb3fb4f3Stomee     getValue()
130fb3fb4f3Stomee     {
131fb3fb4f3Stomee 	double total = 0;
132fb3fb4f3Stomee 	List <Distribution.Bucket> buckets = getBuckets();
133fb3fb4f3Stomee 	for (Distribution.Bucket bucket : buckets) {
134fb3fb4f3Stomee 	    total += ((double)bucket.getFrequency() * (double)bucket.getMin());
135fb3fb4f3Stomee 	}
136fb3fb4f3Stomee 	return (new Double(total));
137fb3fb4f3Stomee     }
138fb3fb4f3Stomee 
139fb3fb4f3Stomee     private long
getZeroBucketValue()140fb3fb4f3Stomee     getZeroBucketValue()
141fb3fb4f3Stomee     {
142fb3fb4f3Stomee 	Distribution.Bucket b = get(ZERO_BUCKET_INDEX);
143fb3fb4f3Stomee 	return b.getFrequency();
144fb3fb4f3Stomee     }
145fb3fb4f3Stomee 
146fb3fb4f3Stomee     /**
147fb3fb4f3Stomee      * Compares the {@code double} values of {@link #getValue()} for
148fb3fb4f3Stomee      * overall magnitude, and if those are equal, compares the
149fb3fb4f3Stomee      * frequencies at the zero bucket (the bucket whose range has a
150fb3fb4f3Stomee      * minimum and maximum value of zero).
151fb3fb4f3Stomee      */
152fb3fb4f3Stomee     public int
compareTo(LogDistribution d)153fb3fb4f3Stomee     compareTo(LogDistribution d)
154fb3fb4f3Stomee     {
155fb3fb4f3Stomee 	Number v1 = getValue();
156fb3fb4f3Stomee 	Number v2 = d.getValue();
157fb3fb4f3Stomee 	double d1 = v1.doubleValue();
158fb3fb4f3Stomee 	double d2 = v2.doubleValue();
159fb3fb4f3Stomee 	int cmp = (d1 < d2 ? -1 : (d1 > d2 ? 1 : 0));
160fb3fb4f3Stomee 	if (cmp == 0) {
161fb3fb4f3Stomee 	    long z1 = getZeroBucketValue();
162fb3fb4f3Stomee 	    long z2 = d.getZeroBucketValue();
163fb3fb4f3Stomee 	    cmp = (z1 < z2 ? -1 : (z1 > z2 ? 1 : 0));
164fb3fb4f3Stomee 	}
165fb3fb4f3Stomee 	return (cmp);
166fb3fb4f3Stomee     }
167fb3fb4f3Stomee 
168fb3fb4f3Stomee     private void
readObject(ObjectInputStream s)169fb3fb4f3Stomee     readObject(ObjectInputStream s)
170fb3fb4f3Stomee             throws IOException, ClassNotFoundException
171fb3fb4f3Stomee     {
172fb3fb4f3Stomee 	s.defaultReadObject();
17391cfa10aStomee 	try {
17491cfa10aStomee 	    initialize();
17591cfa10aStomee 	} catch (Exception e) {
176*4ae67516Stomee 	    InvalidObjectException x = new InvalidObjectException(
177*4ae67516Stomee 		    e.getMessage());
178*4ae67516Stomee 	    x.initCause(e);
179*4ae67516Stomee 	    throw x;
18091cfa10aStomee 	}
181fb3fb4f3Stomee     }
182fb3fb4f3Stomee }
183