1*ae94d716SRichard Lowe /* 2*ae94d716SRichard Lowe * This file and its contents are supplied under the terms of the 3*ae94d716SRichard Lowe * Common Development and Distribution License ("CDDL"), version 1.0. 4*ae94d716SRichard Lowe * You may only use this file in accordance with the terms of version 5*ae94d716SRichard Lowe * 1.0 of the CDDL. 6*ae94d716SRichard Lowe * 7*ae94d716SRichard Lowe * A full copy of the text of the CDDL should have accompanied this 8*ae94d716SRichard Lowe * source. A copy of the CDDL is also available via the Internet at 9*ae94d716SRichard Lowe * http://www.illumos.org/license/CDDL. 10*ae94d716SRichard Lowe */ 11*ae94d716SRichard Lowe 12*ae94d716SRichard Lowe /* 13*ae94d716SRichard Lowe * Copyright 2011, Richard Lowe 14*ae94d716SRichard Lowe */ 15*ae94d716SRichard Lowe 16*ae94d716SRichard Lowe package org.opensolaris.os.dtrace; 17*ae94d716SRichard Lowe 18*ae94d716SRichard Lowe import java.beans.*; 19*ae94d716SRichard Lowe import java.io.*; 20*ae94d716SRichard Lowe import java.util.*; 21*ae94d716SRichard Lowe 22*ae94d716SRichard Lowe /** 23*ae94d716SRichard Lowe * A log/linear distribution aggregated by the DTrace {@code llquantize()} 24*ae94d716SRichard Lowe * action. Aggregated values are aggregated logarithmicly by order of 25*ae94d716SRichard Lowe * magnitude (between the low and high magnitude arguments of the {@code 26*ae94d716SRichard Lowe * llquantize()} action, but linearly within each order of magnitude bounded 27*ae94d716SRichard Lowe * by the step parameter of the {@code llquantize()} action. 28*ae94d716SRichard Lowe * 29*ae94d716SRichard Lowe * @see LinearDistribution 30*ae94d716SRichard Lowe * @see LogLinearDistribution 31*ae94d716SRichard Lowe * @see Aggregation 32*ae94d716SRichard Lowe */ 33*ae94d716SRichard Lowe public final class LogLinearDistribution extends Distribution 34*ae94d716SRichard Lowe implements Serializable, Comparable <LogLinearDistribution> 35*ae94d716SRichard Lowe { 36*ae94d716SRichard Lowe static final long serialVersionUID = 6271156690706677711L; 37*ae94d716SRichard Lowe 38*ae94d716SRichard Lowe static final long UINT16_MAX = 0xffff; 39*ae94d716SRichard Lowe 40*ae94d716SRichard Lowe static final long FACTOR_SHIFT = 48; 41*ae94d716SRichard Lowe static final long LOW_SHIFT = 32; 42*ae94d716SRichard Lowe static final long HIGH_SHIFT = 16; 43*ae94d716SRichard Lowe static final long NSTEP_SHIFT = 0; 44*ae94d716SRichard Lowe unpack(long x, long thing)45*ae94d716SRichard Lowe private static long unpack(long x, long thing) { 46*ae94d716SRichard Lowe return (x & (UINT16_MAX << thing)) >> thing; 47*ae94d716SRichard Lowe } 48*ae94d716SRichard Lowe 49*ae94d716SRichard Lowe /** @serial */ 50*ae94d716SRichard Lowe private long encValue; 51*ae94d716SRichard Lowe /** @serial */ 52*ae94d716SRichard Lowe private long base; 53*ae94d716SRichard Lowe 54*ae94d716SRichard Lowe static { 55*ae94d716SRichard Lowe try { 56*ae94d716SRichard Lowe BeanInfo info = Introspector.getBeanInfo( 57*ae94d716SRichard Lowe LogLinearDistribution.class); 58*ae94d716SRichard Lowe PersistenceDelegate persistenceDelegate = 59*ae94d716SRichard Lowe new DefaultPersistenceDelegate( 60*ae94d716SRichard Lowe new String[] { "encValue", "base", "buckets" }); 61*ae94d716SRichard Lowe BeanDescriptor d = info.getBeanDescriptor(); 62*ae94d716SRichard Lowe d.setValue("persistenceDelegate", persistenceDelegate); 63*ae94d716SRichard Lowe } catch (IntrospectionException e) { 64*ae94d716SRichard Lowe System.out.println(e); 65*ae94d716SRichard Lowe } 66*ae94d716SRichard Lowe } 67*ae94d716SRichard Lowe 68*ae94d716SRichard Lowe /** 69*ae94d716SRichard Lowe * Called by the native C code 70*ae94d716SRichard Lowe */ LogLinearDistribution(long constant, long[] frequencies)71*ae94d716SRichard Lowe private LogLinearDistribution(long constant, long[] frequencies) { 72*ae94d716SRichard Lowe super(0, constant, frequencies); 73*ae94d716SRichard Lowe encValue = constant; 74*ae94d716SRichard Lowe } 75*ae94d716SRichard Lowe 76*ae94d716SRichard Lowe 77*ae94d716SRichard Lowe /** 78*ae94d716SRichard Lowe * Creates a log/linear distribution with the given parameters, base value 79*ae94d716SRichard Lowe * and frequencies. Used by XML Persistence. 80*ae94d716SRichard Lowe * 81*ae94d716SRichard Lowe * @param enc The encoded representation of the high, low, step and steps 82*ae94d716SRichard Lowe * {@code llquantize()} paramaters. 83*ae94d716SRichard Lowe * @param base The base value of the distirbution 84*ae94d716SRichard Lowe * @param frequencies list of frequencies in each bucket range 85*ae94d716SRichard Lowe */ LogLinearDistribution(long enc, long base, List<Bucket> frequencies)86*ae94d716SRichard Lowe public LogLinearDistribution(long enc, long base, 87*ae94d716SRichard Lowe List<Bucket> frequencies) { 88*ae94d716SRichard Lowe super(frequencies); 89*ae94d716SRichard Lowe 90*ae94d716SRichard Lowe encValue = enc; 91*ae94d716SRichard Lowe base = base; 92*ae94d716SRichard Lowe 93*ae94d716SRichard Lowe initialize(); 94*ae94d716SRichard Lowe } 95*ae94d716SRichard Lowe 96*ae94d716SRichard Lowe /** 97*ae94d716SRichard Lowe * Creates a log/linear distribution with the given parameters, base 98*ae94d716SRichard Lowe * values and frequencies. 99*ae94d716SRichard Lowe * 100*ae94d716SRichard Lowe * @param scaleFactor factor 101*ae94d716SRichard Lowe * @param lowMagnitude the low magnitude 102*ae94d716SRichard Lowe * @param highMagnitude the high magnitude 103*ae94d716SRichard Lowe * @param bucketSteps number of linear steps per magnitude 104*ae94d716SRichard Lowe * @param baseVal basue value 105*ae94d716SRichard Lowe * @param frequencies list of frequencies in each bucket range 106*ae94d716SRichard Lowe */ LogLinearDistribution(long scaleFactor, long lowMagnitude, long highMagnitude, long bucketSteps, long baseVal, List<Bucket> frequencies)107*ae94d716SRichard Lowe public LogLinearDistribution(long scaleFactor, long lowMagnitude, 108*ae94d716SRichard Lowe long highMagnitude, long bucketSteps, long baseVal, 109*ae94d716SRichard Lowe List<Bucket> frequencies) { 110*ae94d716SRichard Lowe 111*ae94d716SRichard Lowe super(frequencies); 112*ae94d716SRichard Lowe 113*ae94d716SRichard Lowe encValue = (scaleFactor << FACTOR_SHIFT) | (lowMagnitude << LOW_SHIFT) | 114*ae94d716SRichard Lowe (highMagnitude << HIGH_SHIFT) | (bucketSteps << NSTEP_SHIFT); 115*ae94d716SRichard Lowe base = baseVal; 116*ae94d716SRichard Lowe 117*ae94d716SRichard Lowe initialize(); 118*ae94d716SRichard Lowe } 119*ae94d716SRichard Lowe 120*ae94d716SRichard Lowe private long[][] rangeCache = null; 121*ae94d716SRichard Lowe fillRangeCache(long constant, int len)122*ae94d716SRichard Lowe private void fillRangeCache(long constant, int len) { 123*ae94d716SRichard Lowe long value = 1; 124*ae94d716SRichard Lowe long next, step; 125*ae94d716SRichard Lowe long low, high, nsteps, factor; 126*ae94d716SRichard Lowe int order, bucket = 0; 127*ae94d716SRichard Lowe 128*ae94d716SRichard Lowe low = unpack(constant, LOW_SHIFT); 129*ae94d716SRichard Lowe high = unpack(constant, HIGH_SHIFT); 130*ae94d716SRichard Lowe nsteps = unpack(constant, NSTEP_SHIFT); 131*ae94d716SRichard Lowe factor = unpack(constant, FACTOR_SHIFT); 132*ae94d716SRichard Lowe 133*ae94d716SRichard Lowe if (rangeCache == null) 134*ae94d716SRichard Lowe rangeCache = new long[len][2]; 135*ae94d716SRichard Lowe 136*ae94d716SRichard Lowe for (order = 0; order < low; order++) 137*ae94d716SRichard Lowe value *= factor; 138*ae94d716SRichard Lowe 139*ae94d716SRichard Lowe base = value; 140*ae94d716SRichard Lowe 141*ae94d716SRichard Lowe rangeCache[bucket][0] = Long.MIN_VALUE; 142*ae94d716SRichard Lowe rangeCache[bucket][1] = value - 1; 143*ae94d716SRichard Lowe bucket++; 144*ae94d716SRichard Lowe 145*ae94d716SRichard Lowe next = value * factor; 146*ae94d716SRichard Lowe step = (next > nsteps) ? (next / nsteps) : 1; 147*ae94d716SRichard Lowe 148*ae94d716SRichard Lowe while (order <= high) { 149*ae94d716SRichard Lowe rangeCache[bucket][0] = value; 150*ae94d716SRichard Lowe rangeCache[bucket][1] = value + step - 1; 151*ae94d716SRichard Lowe bucket++; 152*ae94d716SRichard Lowe 153*ae94d716SRichard Lowe if ((value += step) != next) 154*ae94d716SRichard Lowe continue; 155*ae94d716SRichard Lowe 156*ae94d716SRichard Lowe next = value * factor; 157*ae94d716SRichard Lowe step = (next > nsteps) ? (next / nsteps) : 1; 158*ae94d716SRichard Lowe order++; 159*ae94d716SRichard Lowe } 160*ae94d716SRichard Lowe 161*ae94d716SRichard Lowe rangeCache[bucket][0] = value; 162*ae94d716SRichard Lowe rangeCache[bucket][1] = Long.MAX_VALUE; 163*ae94d716SRichard Lowe } 164*ae94d716SRichard Lowe 165*ae94d716SRichard Lowe /** 166*ae94d716SRichard Lowe * Gets a two element array: the first element is the range minimum 167*ae94d716SRichard Lowe * (inclusive), the second element is the range maximum (inclusive). 168*ae94d716SRichard Lowe */ 169*ae94d716SRichard Lowe @Override getBucketRange(int i, int len, long base, long constant)170*ae94d716SRichard Lowe long[] getBucketRange(int i, int len, long base, long constant) { 171*ae94d716SRichard Lowe if (rangeCache == null) 172*ae94d716SRichard Lowe fillRangeCache(constant, len); 173*ae94d716SRichard Lowe 174*ae94d716SRichard Lowe return rangeCache[i]; 175*ae94d716SRichard Lowe } 176*ae94d716SRichard Lowe 177*ae94d716SRichard Lowe @Override getBucketRange(int i, int len)178*ae94d716SRichard Lowe long[] getBucketRange(int i, int len) { 179*ae94d716SRichard Lowe return getBucketRange(i, len, 0, encValue); 180*ae94d716SRichard Lowe } 181*ae94d716SRichard Lowe getValue()182*ae94d716SRichard Lowe public Number getValue() { 183*ae94d716SRichard Lowe double total = 0; 184*ae94d716SRichard Lowe 185*ae94d716SRichard Lowe List<Distribution.Bucket> buckets = getBuckets(); 186*ae94d716SRichard Lowe for (Distribution.Bucket bucket : buckets) 187*ae94d716SRichard Lowe total += ((double)bucket.getFrequency() * (double)bucket.getMin()); 188*ae94d716SRichard Lowe 189*ae94d716SRichard Lowe return (new Double(total)); 190*ae94d716SRichard Lowe } 191*ae94d716SRichard Lowe getZeroBucketValue()192*ae94d716SRichard Lowe private long getZeroBucketValue() { 193*ae94d716SRichard Lowe for (Distribution.Bucket b : this) { 194*ae94d716SRichard Lowe if (b.getMin() == 0) { 195*ae94d716SRichard Lowe return b.getFrequency(); 196*ae94d716SRichard Lowe } 197*ae94d716SRichard Lowe } 198*ae94d716SRichard Lowe return 0; 199*ae94d716SRichard Lowe } 200*ae94d716SRichard Lowe 201*ae94d716SRichard Lowe /** 202*ae94d716SRichard Lowe * Compares the {@code double} values of {@link #getValue()} for overall 203*ae94d716SRichard Lowe * magnitude, and if those are equal, compares frequencies at zero if the 204*ae94d716SRichard Lowe * distrubions includea bucket whose range has a minimum of zero. 205*ae94d716SRichard Lowe */ compareTo(LogLinearDistribution d)206*ae94d716SRichard Lowe public int compareTo(LogLinearDistribution d) { 207*ae94d716SRichard Lowe Number v1 = getValue(); 208*ae94d716SRichard Lowe Number v2 = getValue(); 209*ae94d716SRichard Lowe double d1 = v1.doubleValue(); 210*ae94d716SRichard Lowe double d2 = v2.doubleValue(); 211*ae94d716SRichard Lowe int cmp = (d1 < d2 ? -1 : (d1 > d2 ? 1 : 0)); 212*ae94d716SRichard Lowe 213*ae94d716SRichard Lowe if (cmp == 0) { 214*ae94d716SRichard Lowe long z1 = getZeroBucketValue(); 215*ae94d716SRichard Lowe long z2 = d.getZeroBucketValue(); 216*ae94d716SRichard Lowe cmp = (z1 < z2 ? -1 : (z1 > z2 ? 1 : 0)); 217*ae94d716SRichard Lowe } 218*ae94d716SRichard Lowe return (cmp); 219*ae94d716SRichard Lowe } 220*ae94d716SRichard Lowe getBase()221*ae94d716SRichard Lowe public long getBase() { 222*ae94d716SRichard Lowe return base; 223*ae94d716SRichard Lowe } 224*ae94d716SRichard Lowe getEncValue()225*ae94d716SRichard Lowe public long getEncValue() { 226*ae94d716SRichard Lowe return encValue; 227*ae94d716SRichard Lowe } 228*ae94d716SRichard Lowe readObject(ObjectInputStream s)229*ae94d716SRichard Lowe private void readObject(ObjectInputStream s) 230*ae94d716SRichard Lowe throws IOException, ClassNotFoundException { 231*ae94d716SRichard Lowe s.defaultReadObject(); 232*ae94d716SRichard Lowe try { 233*ae94d716SRichard Lowe initialize(); 234*ae94d716SRichard Lowe } catch (Exception e) { 235*ae94d716SRichard Lowe InvalidObjectException x = new InvalidObjectException( 236*ae94d716SRichard Lowe e.getMessage()); 237*ae94d716SRichard Lowe x.initCause(e); 238*ae94d716SRichard Lowe throw x; 239*ae94d716SRichard Lowe } 240*ae94d716SRichard Lowe } 241*ae94d716SRichard Lowe } 242