KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.nio.channels.FileChannel JavaDoc;
30 import java.nio.MappedByteBuffer JavaDoc;
31 import java.util.TimerTask JavaDoc;
32 import java.util.Timer JavaDoc;
33
34 /**
35  * JRobin backend which is used to store RRD data to ordinary disk files
36  * by using fast java.nio.* package. This is the default backend engine since JRobin 1.4.0.
37  */

38 public class RrdNioBackend extends RrdFileBackend {
39     /**
40      * Defines <code>System.gc()</code> usage policy for this backend.<p>
41      *
42      * NIO backend uses potentially large in-memory buffer to cache file data.
43      * The buffer remains 'active' (by prohibiting file re-creation with the smaller file size)
44      * as long as it is not garbage-collected. By forcing <code>System.gc()</code> call where
45      * appropriate, this backend will free in-memory buffers sooner and file re-creation won't fail.<p>
46      *
47      * The constant is set to <b><code>true</code></b> initially and currently there is no
48      * API to change it during runtime.
49      *
50      * Garbage collection will be forced only in some special circumstances.
51      * It should not affect the speed of your application significantly.<p>
52      */

53     public static final boolean SHOULD_GC = true;
54
55     static {
56         if(SHOULD_GC) {
57             final Runtime JavaDoc runtime = Runtime.getRuntime();
58             runtime.addShutdownHook(new Thread JavaDoc() {
59                 public void run() {
60                     runtime.runFinalization();
61                     runtime.gc();
62                 }
63             });
64         }
65     }
66
67     private static final Timer JavaDoc syncTimer = new Timer JavaDoc(true);
68
69     private int syncMode;
70     MappedByteBuffer JavaDoc byteBuffer;
71     private TimerTask JavaDoc syncTask;
72
73     protected RrdNioBackend(String JavaDoc path, boolean readOnly, int lockMode, int syncMode, int syncPeriod)
74             throws IOException JavaDoc {
75         super(path, readOnly, lockMode);
76         map(readOnly);
77         this.syncMode = syncMode;
78         if(syncMode == RrdNioBackendFactory.SYNC_BACKGROUND && !readOnly) {
79             createSyncTask(syncPeriod);
80         }
81     }
82
83     private void map(boolean readOnly) throws IOException JavaDoc {
84         long length = getLength();
85         if(length > 0) {
86             FileChannel.MapMode JavaDoc mapMode =
87                 readOnly? FileChannel.MapMode.READ_ONLY: FileChannel.MapMode.READ_WRITE;
88             byteBuffer = channel.map(mapMode, 0, length);
89         }
90         else {
91             byteBuffer = null;
92         }
93     }
94
95     private void createSyncTask(int syncPeriod) {
96         syncTask = new TimerTask JavaDoc() {
97             public void run() {
98                 sync();
99             }
100         };
101         syncTimer.schedule(syncTask, syncPeriod * 1000L, syncPeriod * 1000L);
102     }
103
104     /**
105      * Sets length of the underlying RRD file. This method is called only once, immediately
106      * after a new RRD file gets created.
107      * @param newLength Length of the RRD file
108      * @throws IOException Thrown in case of I/O error.
109      */

110     protected void setLength(long newLength) throws IOException JavaDoc {
111         if(newLength < getLength()) {
112             // the file will be truncated
113
if(SHOULD_GC) {
114                 byteBuffer = null;
115                 System.gc();
116             }
117         }
118         super.setLength(newLength);
119         map(false);
120     }
121
122     /**
123      * Writes bytes to the underlying RRD file on the disk
124      * @param offset Starting file offset
125      * @param b Bytes to be written.
126      */

127     protected void write(long offset, byte[] b) {
128         synchronized(byteBuffer) {
129             byteBuffer.position((int)offset);
130             byteBuffer.put(b);
131         }
132     }
133
134     /**
135      * Reads a number of bytes from the RRD file on the disk
136      * @param offset Starting file offset
137      * @param b Buffer which receives bytes read from the file.
138      */

139     protected void read(long offset, byte[] b) {
140         synchronized(byteBuffer) {
141             byteBuffer.position((int)offset);
142             byteBuffer.get(b);
143         }
144     }
145
146     /**
147      * Closes the underlying RRD file.
148      * @throws IOException Thrown in case of I/O error
149      */

150     public void close() throws IOException JavaDoc {
151         // cancel synchronization
152
if(syncTask != null) {
153             syncTask.cancel();
154         }
155         super.close(); // calls sync() eventually
156
// release the buffer, make it eligible for GC as soon as possible
157
byteBuffer = null;
158     }
159
160     /**
161      * This method forces all data cached in memory but not yet stored in the file,
162      * to be stored in it. RrdNioBackend uses (a lot of) memory to cache I/O data.
163      * This method is automatically invoked when the {@link #close()}
164      * method is called. In other words, you don't have to call sync() before you call close().<p>
165      */

166     public void sync() {
167         if(byteBuffer != null) {
168             synchronized(byteBuffer) {
169                 // System.out.println("** SYNC **");
170
byteBuffer.force();
171             }
172         }
173     }
174
175     /**
176      * Method called by the framework immediatelly before RRD update operation starts. This method
177      * will synchronize in-memory cache with the disk content if synchronization mode is set to
178      * {@link RrdNioBackendFactory#SYNC_BEFOREUPDATE}. Otherwise it does nothing.
179      */

180     protected void beforeUpdate() {
181         if(syncMode == RrdNioBackendFactory.SYNC_BEFOREUPDATE) {
182             sync();
183         }
184     }
185
186     /**
187      * Method called by the framework immediatelly after RRD update operation finishes. This method
188      * will synchronize in-memory cache with the disk content if synchronization mode is set to
189      * {@link RrdNioBackendFactory#SYNC_AFTERUPDATE}. Otherwise it does nothing.
190      */

191     protected void afterUpdate() {
192         if(syncMode == RrdNioBackendFactory.SYNC_AFTERUPDATE) {
193             sync();
194         }
195     }
196
197     /**
198      * Method called by the framework immediatelly before RRD fetch operation starts. This method
199      * will synchronize in-memory cache with the disk content if synchronization mode is set to
200      * {@link RrdNioBackendFactory#SYNC_BEFOREFETCH}. Otherwise it does nothing.
201      */

202     protected void beforeFetch() {
203         if(syncMode == RrdNioBackendFactory.SYNC_BEFOREFETCH) {
204             sync();
205         }
206     }
207
208     /**
209      * Method called by the framework immediatelly after RRD fetch operation finishes. This method
210      * will synchronize in-memory cache with the disk content if synchronization mode is set to
211      * {@link RrdNioBackendFactory#SYNC_AFTERFETCH}. Otherwise it does nothing.
212      */

213     protected void afterFetch() {
214         if(syncMode == RrdNioBackendFactory.SYNC_AFTERFETCH) {
215             sync();
216         }
217     }
218 }
219
Popular Tags