KickJava   Java API By Example, From Geeks To Geeks.

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


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  * Base implementation class for all backend classes. Each Round Robin Database object
32  * ({@link RrdDb} object) is backed with a single RrdBackend object which performs
33  * actual I/O operations on the underlying storage. JRobin supports
34  * three different bakcends out of the box:</p>
35  * <ul>
36  * <li>{@link RrdFileBackend}: objects of this class are created from the
37  * {@link RrdFileBackendFactory} class. This was the default backend used in all
38  * JRobin releases prior to 1.4.0. It uses java.io.* package and
39  * RandomAccessFile class to store RRD data in files on the disk.
40  *
41  * <li>{@link RrdNioBackend}: objects of this class are created from the
42  * {@link RrdNioBackendFactory} class. The backend uses java.io.* and java.nio.*
43  * classes (mapped ByteBuffer) to store RRD data in files on the disk. This backend is fast, very fast,
44  * but consumes a lot of memory (borrowed not from the JVM but from the underlying operating system
45  * directly). <b>This is the default backend used in JRobin since 1.4.0 release.</b>
46  *
47  * <li>{@link RrdMemoryBackend}: objects of this class are created from the
48  * {@link RrdMemoryBackendFactory} class. This backend stores all data in memory. Once
49  * JVM exits, all data gets lost. The backend is extremely fast and memory hungry.
50  * </ul>
51  *
52  * To create your own backend in order to provide some custom type of RRD storage,
53  * you should do the following:</p>
54  *
55  * <ul>
56  * <li>Create your custom RrdBackend class (RrdCustomBackend, for example)
57  * by extending RrdBackend class. You have to implement all abstract methods defined
58  * in the base class.
59  *
60  * <li>Create your custom RrdBackendFactory class (RrdCustomBackendFactory,
61  * for example) by extending RrdBackendFactory class. You have to implement all
62  * abstract methods defined in the base class. Your custom factory class will actually
63  * create custom backend objects when necessary.
64  *
65  * <li>Create instance of your custom RrdBackendFactory and register it as a regular
66  * factory available to JRobin framework. See javadoc for {@link RrdBackendFactory} to
67  * find out how to do this
68  * </ul>
69  *
70  */

71 public abstract class RrdBackend {
72     private String JavaDoc path;
73     private static long count = 0;
74
75     /**
76      * Creates backend for a RRD storage with the given path.
77      * @param path String identifying RRD storage. For files on the disk, this
78      * argument should represent file path. Other storage types might interpret
79      * this argument differently.
80      */

81     protected RrdBackend(String JavaDoc path) {
82         this.path = path;
83         count++;
84     }
85
86     /**
87      * Returns path to the storage.
88      * @return Storage path
89      */

90     public String JavaDoc getPath() {
91         return path;
92     }
93
94     /**
95      * Writes an array of bytes to the underlying storage starting from the given
96      * storage offset.
97      * @param offset Storage offset.
98      * @param b Array of bytes that should be copied to the underlying storage
99      * @throws IOException Thrown in case of I/O error
100      */

101     protected abstract void write(long offset, byte[] b) throws IOException JavaDoc;
102
103     /**
104      * Reads an array of bytes from the underlying storage starting from the given
105      * storage offset.
106      * @param offset Storage offset.
107      * @param b Array which receives bytes from the underlying storage
108      * @throws IOException Thrown in case of I/O error
109      */

110     protected abstract void read(long offset, byte[] b) throws IOException JavaDoc;
111
112     /**
113      * Reads all RRD bytes from the underlying storage
114      * @return RRD bytes
115      * @throws IOException Thrown in case of I/O error
116      */

117     public final byte[] readAll() throws IOException JavaDoc {
118         byte[] b = new byte[(int) getLength()];
119         read(0, b);
120         return b;
121     }
122
123     /**
124      * Returns the number of RRD bytes in the underlying storage.
125      * @return Number of RRD bytes in the storage.
126      * @throws IOException Thrown in case of I/O error.
127      */

128     public abstract long getLength() throws IOException JavaDoc;
129
130     /**
131      * Sets the number of bytes in the underlying RRD storage.
132      * This method is called only once, immediately after a new RRD storage gets created.
133      * @param length Length of the underlying RRD storage in bytes.
134      * @throws IOException Thrown in case of I/O error.
135      */

136     protected abstract void setLength(long length) throws IOException JavaDoc;
137
138     /**
139      * Closes the underlying storage. Calls sync() implicitly.
140      * In other words, you don't have to call sync() before close() in order to preserve
141      * data cached in memory.
142      * @throws IOException Thrown in case of I/O error
143      */

144     public void close() throws IOException JavaDoc {
145         sync();
146     }
147
148     /**
149      * Method called by the framework immediatelly before RRD update operation starts. This method
150      * does nothing, but can be overriden in subclasses.
151      */

152     protected void beforeUpdate() throws IOException JavaDoc {
153     }
154
155     /**
156      * Method called by the framework immediatelly after RRD update operation is completed. This method
157      * does nothing, but can be overriden in subclasses.
158      */

159     protected void afterUpdate() throws IOException JavaDoc {
160     }
161
162     /**
163      * Method called by the framework immediatelly before RRD fetch operation starts. This method
164      * does nothing, but can be overriden in subclasses.
165      */

166     protected void beforeFetch() throws IOException JavaDoc {
167     }
168
169     /**
170      * Method called by the framework immediatelly after RRD fetch operation is completed. This method
171      * does nothing, but can be overriden in subclasses.
172      */

173     protected void afterFetch() throws IOException JavaDoc {
174     }
175
176     /**
177      * Method called by the framework immediatelly after RrdDb obejct is created. This method
178      * does nothing, but can be overriden in subclasses.
179      */

180     protected void afterCreate() throws IOException JavaDoc {
181     }
182
183     /**
184      * This method forces all data cached in memory but not yet stored in the persistant
185      * storage, to be stored in it. In the base class this method does nothing but
186      * subclasses might provide real functionality.<p>
187      *
188      * @throws IOException Thrown in case of I/O error
189      */

190     public void sync() throws IOException JavaDoc {
191     }
192
193     final void writeInt(long offset, int value) throws IOException JavaDoc {
194         write(offset, getIntBytes(value));
195     }
196
197     final void writeLong(long offset, long value) throws IOException JavaDoc {
198         write(offset, getLongBytes(value));
199     }
200
201     final void writeDouble(long offset, double value) throws IOException JavaDoc {
202         write(offset, getDoubleBytes(value));
203     }
204
205     final void writeDouble(long offset, double value, int count) throws IOException JavaDoc {
206         byte[] b = getDoubleBytes(value);
207         byte[] image = new byte[8 * count];
208         for(int i = 0, k = 0; i < count; i++) {
209             image[k++] = b[0];
210             image[k++] = b[1];
211             image[k++] = b[2];
212             image[k++] = b[3];
213             image[k++] = b[4];
214             image[k++] = b[5];
215             image[k++] = b[6];
216             image[k++] = b[7];
217         }
218         write(offset, image);
219         image = null;
220     }
221
222     final void writeDouble(long offset, double[] values) throws IOException JavaDoc {
223         int count = values.length;
224         byte[] image = new byte[8 * count];
225         for(int i = 0, k = 0; i < count; i++) {
226             byte[] b = getDoubleBytes(values[i]);
227             image[k++] = b[0];
228             image[k++] = b[1];
229             image[k++] = b[2];
230             image[k++] = b[3];
231             image[k++] = b[4];
232             image[k++] = b[5];
233             image[k++] = b[6];
234             image[k++] = b[7];
235         }
236         write(offset, image);
237         image = null;
238     }
239
240     final void writeString(long offset, String JavaDoc value) throws IOException JavaDoc {
241         value = value.trim();
242         byte[] b = new byte[RrdPrimitive.STRING_LENGTH * 2];
243         for(int i = 0, k = 0; i < RrdPrimitive.STRING_LENGTH; i++) {
244             char c = (i < value.length())? value.charAt(i): ' ';
245             byte[] cb = getCharBytes(c);
246             b[k++] = cb[0];
247             b[k++] = cb[1];
248         }
249         write(offset, b);
250     }
251
252     final int readInt(long offset) throws IOException JavaDoc {
253         byte[] b = new byte[4];
254         read(offset, b);
255         return getInt(b);
256     }
257
258     final long readLong(long offset) throws IOException JavaDoc {
259         byte[] b = new byte[8];
260         read(offset, b);
261         return getLong(b);
262     }
263
264     final double readDouble(long offset) throws IOException JavaDoc {
265         byte[] b = new byte[8];
266         read(offset, b);
267         return getDouble(b);
268     }
269
270     final double[] readDouble(long offset, int count) throws IOException JavaDoc {
271         int byteCount = 8 * count;
272         byte[] image = new byte[byteCount];
273         read(offset, image);
274         double[] values = new double[count];
275         for(int i = 0, k = -1; i < count; i++) {
276             byte[] b = new byte[] {
277                 image[++k], image[++k], image[++k], image[++k],
278                 image[++k], image[++k], image[++k], image[++k]
279             };
280             values[i] = getDouble(b);
281         }
282         image = null;
283         return values;
284     }
285
286     final String JavaDoc readString(long offset) throws IOException JavaDoc {
287         byte[] b = new byte[RrdPrimitive.STRING_LENGTH * 2];
288         char[] c = new char[RrdPrimitive.STRING_LENGTH];
289         read(offset, b);
290         for(int i = 0, k = -1; i < RrdPrimitive.STRING_LENGTH; i++) {
291             byte[] cb = new byte[] { b[++k], b[++k] };
292             c[i] = getChar(cb);
293         }
294         return new String JavaDoc(c).trim();
295     }
296
297     // static helper methods
298

299     private final static byte[] getIntBytes(int value) {
300         byte[] b = new byte[4];
301         b[0] = (byte)((value >>> 24) & 0xFF);
302         b[1] = (byte)((value >>> 16) & 0xFF);
303         b[2] = (byte)((value >>> 8) & 0xFF);
304         b[3] = (byte)((value >>> 0) & 0xFF);
305         return b;
306     }
307
308     private final static byte[] getLongBytes(long value) {
309         byte[] b = new byte[8];
310         b[0] = (byte)((int)(value >>> 56) & 0xFF);
311         b[1] = (byte)((int)(value >>> 48) & 0xFF);
312         b[2] = (byte)((int)(value >>> 40) & 0xFF);
313         b[3] = (byte)((int)(value >>> 32) & 0xFF);
314         b[4] = (byte)((int)(value >>> 24) & 0xFF);
315         b[5] = (byte)((int)(value >>> 16) & 0xFF);
316         b[6] = (byte)((int)(value >>> 8) & 0xFF);
317         b[7] = (byte)((int)(value >>> 0) & 0xFF);
318         return b;
319     }
320
321     private final static byte[] getCharBytes(char value) {
322         byte[] b = new byte[2];
323         b[0] = (byte)((value >>> 8) & 0xFF);
324         b[1] = (byte)((value >>> 0) & 0xFF);
325         return b;
326     }
327
328     private final static byte[] getDoubleBytes(double value) {
329         byte[] bytes = getLongBytes(Double.doubleToLongBits(value));
330         return bytes;
331     }
332
333     private final static int getInt(byte[] b) {
334         assert b.length == 4: "Invalid number of bytes for integer conversion";
335         return ((b[0] << 24) & 0xFF000000) + ((b[1] << 16) & 0x00FF0000) +
336             ((b[2] << 8) & 0x0000FF00) + ((b[3] << 0) & 0x000000FF);
337     }
338
339     private final static long getLong(byte[] b) {
340         assert b.length == 8: "Invalid number of bytes for long conversion";
341         int high = getInt(new byte[] { b[0], b[1], b[2], b[3] });
342         int low = getInt(new byte[] { b[4], b[5], b[6], b[7] });
343         long value = ((long)(high) << 32) + (low & 0xFFFFFFFFL);
344         return value;
345     }
346
347     private final static char getChar(byte[] b) {
348         assert b.length == 2: "Invalid number of bytes for char conversion";
349         return (char)(((b[0] << 8) & 0x0000FF00)
350                 + ((b[1] << 0) & 0x000000FF));
351     }
352
353     private final static double getDouble(byte[] b) {
354         assert b.length == 8: "Invalid number of bytes for double conversion";
355         return Double.longBitsToDouble(getLong(b));
356     }
357
358     static long getCount() {
359         return count;
360     }
361 }
362
Popular Tags