1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * ident	"%Z%%M%	%I%	%E% SMI"
27  */
28 package org.opensolaris.os.dtrace;
29 
30 import java.io.*;
31 import java.beans.*;
32 
33 /**
34  * A {@code long} value aggregated by the DTrace {@code avg()} action.
35  * <p>
36  * Immutable.  Supports persistence using {@link java.beans.XMLEncoder}.
37  *
38  * @see Aggregation
39  * @author Tom Erickson
40  */
41 public final class AvgValue extends AbstractAggregationValue {
42     static final long serialVersionUID = 1633169020110237906L;
43 
44     /** @serial */
45     private final long total;
46     /** @serial */
47     private final long count;
48 
49     static {
50 	try {
51 	    BeanInfo info = Introspector.getBeanInfo(AvgValue.class);
52 	    PersistenceDelegate persistenceDelegate =
53 		    new DefaultPersistenceDelegate(
54 		    new String[] {"value", "total", "count"});
55 	    BeanDescriptor d = info.getBeanDescriptor();
56 	    d.setValue("persistenceDelegate", persistenceDelegate);
57 	} catch (IntrospectionException e) {
58 	    System.out.println(e);
59 	}
60     }
61 
62     /**
63      * Creates a value aggregated by the DTrace {@code avg()} action.
64      * Supports XML persistence.
65      *
66      * @param v average
67      * @param averagedTotal sum total of all values averaged
68      * @param averagedValueCount number of values averaged
69      * @throws IllegalArgumentException if the given count is negative
70      * or if the given average is not the value expected for the given
71      * total and count
72      */
73     public
AvgValue(long v, long averagedTotal, long averagedValueCount)74     AvgValue(long v, long averagedTotal, long averagedValueCount)
75     {
76 	super(v);
77 	total = averagedTotal;
78 	count = averagedValueCount;
79 	validate();
80     }
81 
82     private final void
validate()83     validate()
84     {
85 	if (count < 0) {
86 	    throw new IllegalArgumentException("count is negative");
87 	}
88 	long average = super.getValue().longValue();
89 	if (count == 0) {
90 	    if (average != 0) {
91 		throw new IllegalArgumentException(
92 			"count of values is zero, average is non-zero (" +
93 			average + ")");
94 	    }
95 	} else {
96 	    if (average != (total / count)) {
97 		throw new IllegalArgumentException(
98 			getValue().toString() + " is not the expected " +
99 			"average of total " + total + " and count " +
100 			count);
101 	    }
102 	}
103     }
104 
105     // Needed to support XML persistence since XMLDecoder cannot find
106     // the public method of the non-public superclass.
107 
108     /**
109      * Gets the average of the aggregated values.
110      *
111      * @return average of the aggregated values, equal to <code>({@link
112      * #getTotal()} / {@link #getCount()})</code> rounded down
113      */
114     public Long
getValue()115     getValue()
116     {
117 	return (Long)super.getValue();
118     }
119 
120     /**
121      * Gets the sum total of the aggregated values.
122      *
123      * @return the sum total of the aggregated values
124      */
125     public long
getTotal()126     getTotal()
127     {
128 	return total;
129     }
130 
131     /**
132      * Gets the number of aggregated values included in the average.
133      *
134      * @return the number of aggregated values included in the average
135      */
136     public long
getCount()137     getCount()
138     {
139 	return count;
140     }
141 
142     private void
readObject(ObjectInputStream s)143     readObject(ObjectInputStream s)
144             throws IOException, ClassNotFoundException
145     {
146 	s.defaultReadObject();
147 	// check invariants
148 	try {
149 	    validate();
150 	} catch (Exception e) {
151 	    InvalidObjectException x = new InvalidObjectException(
152 		    e.getMessage());
153 	    x.initCause(e);
154 	    throw x;
155 	}
156     }
157 }
158