View Javadoc
1   /*
2    * Copyright 2005 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package net.sf.sensor.meter;
18  
19  /***
20   * 
21   *
22   */
23  class MeterData {
24  
25    // ==========================================================================
26    // Fields
27    // ==========================================================================
28    
29    /*** The label that uniquely identifies an instance of this class. */
30    private final String label;
31    
32    /*** Lazy-initialized hierarchical (tree) view on this instance. */
33    private MeterStatistics meterStatistics;
34    
35    
36    // ==========================================================================
37    // Statistics Fields
38    // ==========================================================================
39    
40    private long currentValue = 0L;
41    private long sumOfValues = 0L;
42    private long averageValue = 0L;
43    private long minimumValue = 0L;
44    private long maximumValue = 0L;
45    private long standardDeviation = 0L;
46    
47    private long numberOfValueChanges = 0L;
48    private long sumOfSquaresOfValues = 0L;
49    
50    private long timeOfFirstUpdate = 0L;
51    private long timeOfLastUpdate = 0L;
52    
53    
54    // ==========================================================================
55    // Constructors
56    // ==========================================================================
57    
58    /***
59     * Creates a new MeterData instance uniquely identified by the specified label.
60     * 
61     * @param runtime the associated {@link MeterRuntime}.
62     * @param label the label that uniquely identifies an instance of this class.
63     */
64    MeterData(String label) {
65      this.label = label;
66    }
67    
68    
69    // ==========================================================================
70    // Basic API
71    // ==========================================================================
72    
73    /***
74     * Returns the label.
75     * @return Returns the label.
76     */
77    String getLabel() {
78      return label;
79    }
80    
81    /***
82     * Resets all statistics data.
83     */
84    synchronized void reset() {
85      currentValue = 0L;
86      sumOfValues  = 0L;
87      averageValue = 0L;
88      minimumValue = 0L;
89      maximumValue = 0L;
90      standardDeviation = 0L;
91      
92      timeOfFirstUpdate = 0L;
93      timeOfLastUpdate  = 0L;
94      
95      numberOfValueChanges = 0L;
96      sumOfSquaresOfValues = 0L;
97    }
98    
99    
100   // ==========================================================================
101   // Tree structure-related methods (package private) 
102   // ==========================================================================
103   
104   /***
105    * Creates a new instance of Meter linked to this MeterData instance.
106    * @return a new instance of Meter linked to this MeterData instance.
107    */
108   Meter createMeter() {
109     return new Meter(this);
110   }
111   
112   /***
113    * Callback method used by Meter instances to report back a timing measurement.
114    * @param newValue the time (in milliseconds) it took to execute the code that was being measured.
115    */
116   synchronized void updateFromMeter(long newValue) {
117     // update the internal statistics
118     numberOfValueChanges++;
119     currentValue         = newValue;
120     sumOfValues          = sumOfValues + newValue;
121     averageValue         = sumOfValues / numberOfValueChanges;
122     sumOfSquaresOfValues = sumOfSquaresOfValues + (newValue * newValue);
123     
124     // the time of the last update is always the last call to this method.
125     timeOfLastUpdate = System.currentTimeMillis();
126     
127     if (numberOfValueChanges == 1L) {
128       minimumValue      = newValue;
129       maximumValue      = newValue;
130       timeOfFirstUpdate = timeOfLastUpdate;
131     } else {
132       if (newValue < minimumValue) {
133         minimumValue = newValue;
134       }
135     
136       if (newValue > maximumValue) {
137         maximumValue = newValue;
138       }
139     }
140     
141     // calculate the standard deviation
142     long nMinus1 = (numberOfValueChanges <= 1) ? 1 : numberOfValueChanges - 1; // avoid 0 divides
143     long numerator = sumOfSquaresOfValues - ((sumOfValues * sumOfValues) / numberOfValueChanges);
144     
145     standardDeviation = (long) java.lang.Math.sqrt(numerator / nMinus1);
146   }
147   
148   /***
149    * Returns a hierarchical statistical view of this instance of MeterData.
150    * @return a hierarchical statistical view of this instance of MeterData.
151    */
152   MeterStatistics getStatistics() {
153     if (meterStatistics == null) {
154       meterStatistics = new MeterStatistics(this);
155     }
156     
157     // refresh the statistics
158     refreshStatistics();
159     
160     return meterStatistics;
161   }
162   
163   /***
164    * Callback method used by {@link MeterStatistics#refresh()} to extract
165    * the latest data from this instance.
166    * This method is synchronized to prevent half-updated data, etc.
167    * The reason for this elaborate callback mechanism is to get all internal
168    * values out of this instance in one synchronized call instead of calling
169    * a number of synchronized getters from the statistics class. The latter
170    * could lead to inconsistent data.
171    */
172   synchronized void refreshStatistics() {
173     meterStatistics.refreshFromData(
174         currentValue,
175         numberOfValueChanges ,
176         sumOfValues,
177         averageValue,
178         standardDeviation,
179         minimumValue,
180         maximumValue,
181         timeOfFirstUpdate,
182         timeOfLastUpdate,
183         sumOfSquaresOfValues);
184   }
185 
186   
187   // ==========================================================================
188   // Internal statistics getters.
189   // FOR TESTING PURPOSES ONLY !! 
190   // THESE METHODS ARE NOT THREAD SAFE !!
191   // ==========================================================================
192   
193   /***
194    * Returns the currentValue.
195    * @return Returns the currentValue.
196    */
197   long getCurrentValue() {
198     return currentValue;
199   }
200   
201   /***
202    * Returns the numberOfValueChanges.
203    * @return Returns the numberOfValueChanges.
204    */
205   long getNumberOfValueChanges() {
206     return numberOfValueChanges;
207   }
208   
209   /***
210    * Returns the sumOfValues.
211    * @return Returns the sumOfValues.
212    */
213   long getSumOfValues() {
214     return sumOfValues;
215   }
216   
217   /***
218    * Returns the averageValue.
219    * @return Returns the averageValue.
220    */
221   long getAverageValue() {
222     return averageValue;
223   }
224   
225   /***
226    * Returns the sumOfSquaresOfValues.
227    * @return Returns the sumOfSquaresOfValues.
228    */
229   long getSumOfSquaresOfValues() {
230     return sumOfSquaresOfValues;
231   }
232   
233   /***
234    * Returns the standardDeviation.
235    * @return Returns the standardDeviation.
236    */
237   long getStandardDeviation() {
238     return standardDeviation;
239   }
240   
241   /***
242    * Returns the minimumValue.
243    * @return Returns the minimumValue.
244    */
245   long getMinimumValue() {
246     return minimumValue;
247   }
248   
249   /***
250    * Returns the maximumValue.
251    * @return Returns the maximumValue.
252    */
253   long getMaximumValue() {
254     return maximumValue;
255   }
256   
257   /***
258    * Returns the timeOfFirstUpdate.
259    * @return Returns the timeOfFirstUpdate.
260    */
261   long getTimeOfFirstUpdate() {
262     return timeOfFirstUpdate;
263   }
264   
265   /***
266    * Returns the timeOfLastUpdate.
267    * @return Returns the timeOfLastUpdate.
268    */
269   long getTimeOfLastUpdate() {
270     return timeOfLastUpdate;
271   }
272 
273   
274   // ==========================================================================
275   // Standard Object method overrides and simple debugging methods
276   // ==========================================================================
277   
278   /***
279    * @see java.lang.Object#toString()
280    */
281   public String toString() {
282     return "Current value: "              + currentValue
283          + ", Number of value changes: "  + numberOfValueChanges
284          + ", Sum of values: "            + sumOfValues
285          + ", Average value: "            + averageValue
286          + ", Standard deviation: "       + standardDeviation
287          + ", Minimum value: "            + minimumValue
288          + ", Maximum value: "            + maximumValue
289          + ", Time of first update: "     + timeOfFirstUpdate
290          + ", Time of last update: "      + timeOfLastUpdate
291          + ", Sum of squares of values: " + sumOfSquaresOfValues;
292   }
293   
294 }