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