KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jrobin > core > Datasource


1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info: http://www.jrobin.org
6  * Project Lead: Sasa Markovic (saxon@jrobin.org);
7  *
8  * (C) Copyright 2003, by Sasa Markovic.
9  *
10  * Developers: Sasa Markovic (saxon@jrobin.org)
11  * Arne Vandamme (cobralord@jrobin.org)
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25
26 package org.jrobin.core;
27
28 import java.io.IOException JavaDoc;
29
30 /**
31  * Class to represent single datasource within RRD. Each datasource object holds the
32  * following information: datasource definition (once set, never changed) and
33  * datasource state variables (changed whenever RRD gets updated).<p>
34  *
35  * Normally, you don't need to manipluate Datasource objects directly, it's up to
36  * JRobin framework to do it for you.
37  *
38  * @author <a HREF="mailto:saxon@jrobin.org">Sasa Markovic</a>
39  */

40
41 public class Datasource implements RrdUpdater {
42     private RrdDb parentDb;
43     // definition
44
private RrdString dsName, dsType;
45     private RrdLong heartbeat;
46     private RrdDouble minValue, maxValue;
47
48     // state variables
49
private RrdDouble lastValue;
50     private RrdLong nanSeconds;
51     private RrdDouble accumValue;
52
53     Datasource(RrdDb parentDb, DsDef dsDef) throws IOException JavaDoc {
54         boolean shouldInitialize = dsDef != null;
55         this.parentDb = parentDb;
56         dsName = new RrdString(this);
57         dsType = new RrdString(this);
58         heartbeat = new RrdLong(this);
59         minValue = new RrdDouble(this);
60         maxValue = new RrdDouble(this);
61         lastValue = new RrdDouble(this);
62         accumValue = new RrdDouble(this);
63         nanSeconds = new RrdLong(this);
64         if(shouldInitialize) {
65             dsName.set(dsDef.getDsName());
66             dsType.set(dsDef.getDsType());
67             heartbeat.set(dsDef.getHeartbeat());
68             minValue.set(dsDef.getMinValue());
69             maxValue.set(dsDef.getMaxValue());
70             lastValue.set(Double.NaN);
71             accumValue.set(0.0);
72             Header header = parentDb.getHeader();
73             nanSeconds.set(header.getLastUpdateTime() % header.getStep());
74         }
75     }
76
77     Datasource(RrdDb parentDb, DataImporter reader, int dsIndex) throws IOException JavaDoc, RrdException {
78         this(parentDb, null);
79         dsName.set(reader.getDsName(dsIndex));
80         dsType.set(reader.getDsType(dsIndex));
81         heartbeat.set(reader.getHeartbeat(dsIndex));
82         minValue.set(reader.getMinValue(dsIndex));
83         maxValue.set(reader.getMaxValue(dsIndex));
84         lastValue.set(reader.getLastValue(dsIndex));
85         accumValue.set(reader.getAccumValue(dsIndex));
86         nanSeconds.set(reader.getNanSeconds(dsIndex));
87     }
88
89     String JavaDoc dump() throws IOException JavaDoc {
90         return "== DATASOURCE ==\n" +
91             "DS:" + dsName.get() + ":" + dsType.get() + ":" +
92             heartbeat.get() + ":" + minValue.get() + ":" +
93             maxValue.get() + "\nlastValue:" + lastValue.get() +
94             " nanSeconds:" + nanSeconds.get() +
95             " accumValue:" + accumValue.get() + "\n";
96     }
97
98     /**
99      * Returns datasource name.
100      * @return Datasource name
101      * @throws IOException Thrown in case of I/O error
102      */

103     public String JavaDoc getDsName() throws IOException JavaDoc {
104         return dsName.get();
105     }
106
107     /**
108      * Returns datasource type (GAUGE, COUNTER, DERIVE, ABSOLUTE).
109      *
110      * @return Datasource type.
111      * @throws IOException Thrown in case of I/O error
112      */

113     public String JavaDoc getDsType() throws IOException JavaDoc {
114         return dsType.get();
115     }
116
117     /**
118      * Returns datasource heartbeat
119      *
120      * @return Datasource heartbeat
121      * @throws IOException Thrown in case of I/O error
122      */

123
124     public long getHeartbeat() throws IOException JavaDoc {
125         return heartbeat.get();
126     }
127
128     /**
129      * Returns mimimal allowed value for this datasource.
130      *
131      * @return Minimal value allowed.
132      * @throws IOException Thrown in case of I/O error
133      */

134     public double getMinValue() throws IOException JavaDoc {
135         return minValue.get();
136     }
137
138     /**
139      * Returns maximal allowed value for this datasource.
140      *
141      * @return Maximal value allowed.
142      * @throws IOException Thrown in case of I/O error
143      */

144     public double getMaxValue() throws IOException JavaDoc {
145         return maxValue.get();
146     }
147
148     /**
149      * Returns last known value of the datasource.
150      *
151      * @return Last datasource value.
152      * @throws IOException Thrown in case of I/O error
153      */

154     public double getLastValue() throws IOException JavaDoc {
155         return lastValue.get();
156     }
157
158     /**
159      * Returns value this datasource accumulated so far.
160      *
161      * @return Accumulated datasource value.
162      * @throws IOException Thrown in case of I/O error
163      */

164     public double getAccumValue() throws IOException JavaDoc {
165         return accumValue.get();
166     }
167
168     /**
169      * Returns the number of accumulated NaN seconds.
170      *
171      * @return Accumulated NaN seconds.
172      * @throws IOException Thrown in case of I/O error
173      */

174     public long getNanSeconds() throws IOException JavaDoc {
175         return nanSeconds.get();
176     }
177
178     void process(long newTime, double newValue) throws IOException JavaDoc, RrdException {
179         Header header = parentDb.getHeader();
180         long step = header.getStep();
181         long oldTime = header.getLastUpdateTime();
182         long startTime = Util.normalize(oldTime, step);
183         long endTime = startTime + step;
184         double oldValue = lastValue.get();
185         double updateValue = calculateUpdateValue(oldTime, oldValue, newTime, newValue);
186         if(newTime < endTime) {
187             accumulate(oldTime, newTime, updateValue);
188         }
189         else {
190             // should store something
191
long boundaryTime = Util.normalize(newTime, step);
192             accumulate(oldTime, boundaryTime, updateValue);
193             double value = calculateTotal(startTime, boundaryTime);
194             // how many updates?
195
long numSteps= (boundaryTime - endTime) / step + 1L;
196             // ACTION!
197
parentDb.archive(this, value, numSteps);
198             // cleanup
199
nanSeconds.set(0);
200             accumValue.set(0.0);
201             accumulate(boundaryTime, newTime, updateValue);
202         }
203     }
204
205     private double calculateUpdateValue(long oldTime, double oldValue,
206                                         long newTime, double newValue) throws IOException JavaDoc {
207         double updateValue = Double.NaN;
208         if(newTime - oldTime <= heartbeat.get()) {
209             String JavaDoc type = dsType.get();
210             if(type.equals("GAUGE")) {
211                 updateValue = newValue;
212             }
213             else if(type.equals("ABSOLUTE")) {
214                 if(!Double.isNaN(newValue)) {
215                     updateValue = newValue / (newTime - oldTime);
216                 }
217             }
218             else if(type.equals("DERIVE")) {
219                 if(!Double.isNaN(newValue) && !Double.isNaN(oldValue)) {
220                     updateValue = (newValue - oldValue) / (newTime - oldTime);
221                 }
222             }
223             else if(type.equals("COUNTER")) {
224                 if(!Double.isNaN(newValue) && !Double.isNaN(oldValue)) {
225                     double diff = newValue - oldValue;
226                     double max32bit = Math.pow(2, 32);
227                     double max64bit = Math.pow(2, 64);
228                     if(diff < 0) {
229                            diff += max32bit;
230                     }
231                     if(diff < 0) {
232                            diff += max64bit - max32bit;
233                     }
234                     if(diff >= 0) {
235                         updateValue = diff / (newTime - oldTime);
236                     }
237                 }
238             }
239             if(!Double.isNaN(updateValue)) {
240                 double minVal = minValue.get();
241                 double maxVal = maxValue.get();
242                 if(!Double.isNaN(minVal) && updateValue < minVal) {
243                     updateValue = Double.NaN;
244                 }
245                 if(!Double.isNaN(maxVal) && updateValue > maxVal) {
246                     updateValue = Double.NaN;
247                 }
248             }
249         }
250         lastValue.set(newValue);
251         return updateValue;
252     }
253
254     private void accumulate(long oldTime, long newTime, double updateValue) throws IOException JavaDoc {
255         if(Double.isNaN(updateValue)) {
256             nanSeconds.set(nanSeconds.get() + (newTime - oldTime));
257         }
258         else {
259             accumValue.set(accumValue.get() + updateValue * (newTime - oldTime));
260         }
261     }
262
263     private double calculateTotal(long startTime, long boundaryTime) throws IOException JavaDoc {
264         double totalValue = Double.NaN;
265         long validSeconds = boundaryTime - startTime - nanSeconds.get();
266         if(nanSeconds.get() <= heartbeat.get() && validSeconds > 0) {
267             totalValue = accumValue.get() / validSeconds;
268         }
269         return totalValue;
270     }
271
272     void appendXml(XmlWriter writer) throws IOException JavaDoc {
273         writer.startTag("ds");
274         writer.writeTag("name", dsName.get());
275         writer.writeTag("type", dsType.get());
276         writer.writeTag("minimal_heartbeat", heartbeat.get());
277         writer.writeTag("min", minValue.get());
278         writer.writeTag("max", maxValue.get());
279         writer.writeComment("PDP Status");
280         writer.writeTag("last_ds", lastValue.get(), "UNKN");
281         writer.writeTag("value", accumValue.get());
282         writer.writeTag("unknown_sec", nanSeconds.get());
283         writer.closeTag(); // ds
284
}
285
286     /**
287      * Copies object's internal state to another Datasource object.
288      * @param other New Datasource object to copy state to
289      * @throws IOException Thrown in case of I/O error
290      * @throws RrdException Thrown if supplied argument is not a Datasource object
291      */

292     public void copyStateTo(RrdUpdater other) throws IOException JavaDoc, RrdException {
293         if(!(other instanceof Datasource)) {
294             throw new RrdException(
295                 "Cannot copy Datasource object to " + other.getClass().getName());
296         }
297         Datasource datasource = (Datasource) other;
298         if(!datasource.dsName.get().equals(dsName.get())) {
299             throw new RrdException("Incomaptible datasource names");
300         }
301         if(!datasource.dsType.get().equals(dsType.get())) {
302             throw new RrdException("Incomaptible datasource types");
303         }
304         datasource.lastValue.set(lastValue.get());
305         datasource.nanSeconds.set(nanSeconds.get());
306         datasource.accumValue.set(accumValue.get());
307     }
308
309     /**
310      * Returns index of this Datasource object in the RRD.
311      * @return Datasource index in the RRD.
312      * @throws IOException Thrown in case of I/O error
313      */

314     public int getDsIndex() throws IOException JavaDoc {
315         try {
316             return parentDb.getDsIndex(dsName.get());
317         }
318         catch(RrdException e) {
319             return -1;
320         }
321     }
322
323     /**
324      * Sets datasource heartbeat to a new value.
325      * @param heartbeat New heartbeat value
326      * @throws IOException Thrown in case of I/O error
327      * @throws RrdException Thrown if invalid (non-positive) heartbeat value is specified.
328      */

329     public void setHeartbeat(long heartbeat) throws RrdException, IOException JavaDoc {
330         if(heartbeat < 1L) {
331             throw new RrdException("Invalid heartbeat specified: " + heartbeat);
332         }
333         this.heartbeat.set(heartbeat);
334     }
335
336     /**
337      * Sets minimum allowed value for this datasource. If <code>filterArchivedValues</code>
338      * argment is set to true, all archived values less then <code>minValue</code> will
339      * be fixed to NaN.
340      * @param minValue New minimal value. Specify <code>Double.NaN</code> if no minimal
341      * value should be set
342      * @param filterArchivedValues true, if archived datasource values should be fixed;
343      * false, otherwise.
344      * @throws IOException Thrown in case of I/O error
345      * @throws RrdException Thrown if invalid minValue was supplied (not less then maxValue)
346      */

347     public void setMinValue(double minValue, boolean filterArchivedValues)
348         throws IOException JavaDoc, RrdException {
349         double maxValue = this.maxValue.get();
350         if(!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
351             throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
352         }
353         this.minValue.set(minValue);
354         if(!Double.isNaN(minValue) && filterArchivedValues) {
355             int dsIndex = getDsIndex();
356             Archive[] archives = parentDb.getArchives();
357             for(int i = 0; i < archives.length; i++) {
358                 archives[i].getRobin(dsIndex).filterValues(minValue, Double.NaN);
359             }
360         }
361     }
362
363     /**
364      * Sets maximum allowed value for this datasource. If <code>filterArchivedValues</code>
365      * argment is set to true, all archived values greater then <code>maxValue</code> will
366      * be fixed to NaN.
367      * @param maxValue New maximal value. Specify <code>Double.NaN</code> if no max
368      * value should be set.
369      * @param filterArchivedValues true, if archived datasource values should be fixed;
370      * false, otherwise.
371      * @throws IOException Thrown in case of I/O error
372      * @throws RrdException Thrown if invalid maxValue was supplied (not greater then minValue)
373      */

374     public void setMaxValue(double maxValue, boolean filterArchivedValues)
375         throws IOException JavaDoc, RrdException {
376         double minValue = this.minValue.get();
377         if(!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
378             throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
379         }
380         this.maxValue.set(maxValue);
381         if(!Double.isNaN(maxValue) && filterArchivedValues) {
382             int dsIndex = getDsIndex();
383             Archive[] archives = parentDb.getArchives();
384             for(int i = 0; i < archives.length; i++) {
385                 archives[i].getRobin(dsIndex).filterValues(Double.NaN, maxValue);
386             }
387         }
388     }
389
390     /**
391      * Sets min/max values allowed for this datasource. If <code>filterArchivedValues</code>
392      * argment is set to true, all archived values less then <code>minValue</code> or
393      * greater then <code>maxValue</code> will be fixed to NaN.
394      * @param minValue New minimal value. Specify <code>Double.NaN</code> if no min
395      * value should be set.
396      * @param maxValue New maximal value. Specify <code>Double.NaN</code> if no max
397      * value should be set.
398      * @param filterArchivedValues true, if archived datasource values should be fixed;
399      * false, otherwise.
400      * @throws IOException Thrown in case of I/O error
401      * @throws RrdException Thrown if invalid min/max values were supplied
402      */

403     public void setMinMaxValue(double minValue, double maxValue, boolean filterArchivedValues)
404         throws IOException JavaDoc, RrdException {
405         if(!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
406             throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
407         }
408         this.minValue.set(minValue);
409         this.maxValue.set(maxValue);
410         if(!(Double.isNaN(minValue) && Double.isNaN(maxValue)) && filterArchivedValues) {
411             int dsIndex = getDsIndex();
412             Archive[] archives = parentDb.getArchives();
413             for(int i = 0; i < archives.length; i++) {
414                 archives[i].getRobin(dsIndex).filterValues(minValue, maxValue);
415             }
416         }
417     }
418
419     /**
420      * Returns the underlying storage (backend) object which actually performs all
421      * I/O operations.
422      * @return I/O backend object
423      */

424     public RrdBackend getRrdBackend() {
425         return parentDb.getRrdBackend();
426     }
427
428     /**
429      * Required to implement RrdUpdater interface. You should never call this method directly.
430      * @return Allocator object
431      */

432     public RrdAllocator getRrdAllocator() {
433         return parentDb.getRrdAllocator();
434     }
435 }
436
437
Popular Tags