KickJava   Java API By Example, From Geeks To Geeks.

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


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  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * Developers: Sasa Markovic (saxon@jrobin.org)
15  * Arne Vandamme (cobralord@jrobin.org)
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 archive values for a single datasource. Robin class is the heart of
32  * the so-called "round robin database" concept. Basically, each Robin object is a
33  * fixed length array of double values. Each double value reperesents consolidated, archived
34  * value for the specific timestamp. When the underlying array of double values gets completely
35  * filled, new values will replace the oldest ones.<p>
36  *
37  * Robin object does not hold values in memory - such object could be quite large.
38  * Instead of it, Robin reads them from the backend I/O only when necessary.
39  *
40  * @author <a HREF="mailto:saxon@jrobin.org">Sasa Markovic</a>
41  */

42 public class Robin implements RrdUpdater {
43     private Archive parentArc;
44     private RrdInt pointer;
45     private RrdDoubleArray values;
46     private int rows;
47
48     Robin(Archive parentArc, int rows, boolean shouldInitialize) throws IOException JavaDoc {
49         this.parentArc = parentArc;
50         this.pointer = new RrdInt(this);
51         this.values = new RrdDoubleArray(this, rows);
52         this.rows = rows;
53         if(shouldInitialize) {
54             pointer.set(0);
55             values.set(0, Double.NaN, rows);
56         }
57     }
58
59     /**
60      * Fetches all archived values.
61      *
62      * @return Array of double archive values, starting from the oldest one.
63      * @throws IOException Thrown in case of I/O specific error.
64      */

65     public double[] getValues() throws IOException JavaDoc {
66         return getValues(0, rows);
67     }
68
69     // stores single value
70
void store(double newValue) throws IOException JavaDoc {
71         int position = pointer.get();
72         values.set(position, newValue);
73         pointer.set((position + 1) % rows);
74     }
75
76     // stores the same value several times
77
void bulkStore(double newValue, int bulkCount) throws IOException JavaDoc {
78         assert bulkCount <= rows: "Invalid number of bulk updates: " + bulkCount +
79             " rows=" + rows;
80         int position = pointer.get();
81         // update tail
82
int tailUpdateCount = Math.min(rows - position, bulkCount);
83         values.set(position, newValue, tailUpdateCount);
84         pointer.set((position + tailUpdateCount) % rows);
85         // do we need to update from the start?
86
int headUpdateCount = bulkCount - tailUpdateCount;
87         if(headUpdateCount > 0) {
88             values.set(0, newValue, headUpdateCount);
89             pointer.set(headUpdateCount);
90         }
91     }
92
93     // updates Robin values in bulk
94
void update(double[] newValues) throws IOException JavaDoc {
95         assert rows == newValues.length: "Invalid number of values supplied: " + newValues.length +
96             " rows=" + rows;
97         pointer.set(0);
98         values.writeDouble(0, newValues);
99     }
100
101     String JavaDoc dump() throws IOException JavaDoc {
102         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("Robin " + pointer.get() + "/" + rows + ": ");
103         double[] values = getValues();
104         for(int i = 0; i < values.length; i++) {
105             buffer.append(Util.formatDouble(values[i], true) + " ");
106         }
107         buffer.append("\n");
108         return buffer.toString();
109     }
110
111     /**
112      * Returns the i-th value from the Robin archive.
113      * @param index Value index
114      * @return Value stored in the i-th position (the oldest value has zero index)
115      * @throws IOException Thrown in case of I/O specific error.
116      */

117     public double getValue(int index) throws IOException JavaDoc {
118         int arrayIndex = (pointer.get() + index) % rows;
119         return values.get(arrayIndex);
120     }
121
122     double[] getValues(int index, int count) throws IOException JavaDoc {
123         assert count <= rows: "Too many values requested: " + count + " rows=" + rows;
124         int startIndex = (pointer.get() + index) % rows;
125         int tailReadCount = Math.min(rows - startIndex, count);
126         double[] tailValues = values.get(startIndex, tailReadCount);
127         if(tailReadCount < count) {
128             int headReadCount = count - tailReadCount;
129             double[] headValues = values.get(0, headReadCount);
130             double[] values = new double[count];
131             int k = 0;
132             for(int i = 0; i < tailValues.length; i++) {
133                 values[k++] = tailValues[i];
134             }
135             for(int i = 0; i < headValues.length; i++) {
136                 values[k++] = headValues[i];
137             }
138             return values;
139         }
140         else {
141             return tailValues;
142         }
143     }
144
145     /**
146      * Returns the Archive object to which this Robin object belongs.
147      *
148      * @return Parent Archive object
149      */

150     public Archive getParent() {
151         return parentArc;
152     }
153
154     /**
155      * Returns the size of the underlying array of archived values.
156      *
157      * @return Number of stored values
158      */

159     public int getSize() {
160         return rows;
161     }
162
163     /**
164      * Copies object's internal state to another Robin object.
165      * @param other New Robin object to copy state to
166      * @throws IOException Thrown in case of I/O error
167      * @throws RrdException Thrown if supplied argument is not a Robin object
168      */

169     public void copyStateTo(RrdUpdater other) throws IOException JavaDoc, RrdException {
170         if(!(other instanceof Robin)) {
171             throw new RrdException(
172                 "Cannot copy Robin object to " + other.getClass().getName());
173         }
174         Robin robin = (Robin) other;
175         int rowsDiff = rows - robin.rows;
176         if(rowsDiff == 0) {
177             // Identical dimensions. Do copy in BULK to speed things up
178
robin.pointer.set(pointer.get());
179             robin.values.writeBytes(values.readBytes());
180         }
181         else {
182             // different sizes
183
for(int i = 0; i < robin.rows; i++) {
184                 int j = i + rowsDiff;
185                 robin.store(j >= 0? getValue(j): Double.NaN);
186             }
187         }
188     }
189
190     void filterValues(double minValue, double maxValue) throws IOException JavaDoc {
191         for(int i = 0; i < rows; i++) {
192             double value = values.get(i);
193             if(!Double.isNaN(minValue) && !Double.isNaN(value) && minValue > value) {
194                 values.set(i, Double.NaN);
195             }
196             if(!Double.isNaN(maxValue) && !Double.isNaN(value) && maxValue < value) {
197                 values.set(i, Double.NaN);
198             }
199         }
200     }
201
202     /**
203      * Returns the underlying storage (backend) object which actually performs all
204      * I/O operations.
205      * @return I/O backend object
206      */

207     public RrdBackend getRrdBackend() {
208         return parentArc.getRrdBackend();
209     }
210
211     /**
212      * Required to implement RrdUpdater interface. You should never call this method directly.
213      * @return Allocator object
214      */

215     public RrdAllocator getRrdAllocator() {
216         return parentArc.getRrdAllocator();
217     }
218 }
219
Popular Tags