KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.RandomAccessFile JavaDoc;
30 import java.io.File JavaDoc;
31 import java.nio.channels.FileChannel JavaDoc;
32 import java.nio.channels.FileLock JavaDoc;
33 import java.util.HashSet JavaDoc;
34
35 /**
36  * JRobin backend which is used to store RRD data to ordinary files on the disk. This was the
37  * default factory before 1.4.0 version<p>
38  *
39  * This backend is based on the RandomAccessFile class (java.io.* package).
40  */

41 public class RrdFileBackend extends RrdBackend {
42     static final long LOCK_DELAY = 100; // 0.1sec
43

44     private static HashSet JavaDoc openFiles = new HashSet JavaDoc();
45
46     protected RandomAccessFile JavaDoc file;
47     protected FileChannel JavaDoc channel;
48     protected FileLock JavaDoc fileLock;
49
50     protected RrdFileBackend(String JavaDoc path, boolean readOnly, int lockMode) throws IOException JavaDoc {
51         super(path);
52         file = new RandomAccessFile JavaDoc(path, readOnly? "r": "rw");
53         channel = file.getChannel();
54         if(!readOnly) {
55             lockFile(lockMode);
56             // We'll try to lock the file only in "rw" mode
57
registerWriter(path);
58         }
59     }
60
61     private static synchronized void registerWriter(String JavaDoc path) throws IOException JavaDoc {
62         String JavaDoc canonicalPath = getCanonicalPath(path);
63         if(openFiles.contains(canonicalPath)) {
64             throw new IOException JavaDoc("File \"" + path + "\" already open for R/W access. " +
65                     "You cannot open the same file for R/W access twice");
66         }
67         else {
68             openFiles.add(canonicalPath);
69         }
70     }
71
72     private void lockFile(int lockMode) throws IOException JavaDoc {
73         if(lockMode == RrdDb.WAIT_IF_LOCKED || lockMode == RrdDb.EXCEPTION_IF_LOCKED) {
74             do {
75                 fileLock = channel.tryLock();
76                 if(fileLock == null) {
77                     // could not obtain lock
78
if(lockMode == RrdDb.WAIT_IF_LOCKED) {
79                         // wait a little, than try again
80
try {
81                             Thread.sleep(LOCK_DELAY);
82                         } catch (InterruptedException JavaDoc e) {
83                             // NOP
84
}
85                     }
86                     else {
87                         throw new IOException JavaDoc("Access denied. " +
88                             "File [" + getPath() + "] already locked");
89                     }
90                 }
91             } while(fileLock == null);
92         }
93     }
94
95     /**
96      * Closes the underlying RRD file.
97      * @throws IOException Thrown in case of I/O error
98      */

99     public void close() throws IOException JavaDoc {
100         super.close(); // calls sync()
101
unregisterWriter(getPath());
102         unlockFile();
103         channel.close();
104         file.close();
105     }
106
107     private static synchronized void unregisterWriter(String JavaDoc path) throws IOException JavaDoc {
108         String JavaDoc canonicalPath = getCanonicalPath(path);
109         openFiles.remove(canonicalPath);
110     }
111
112     private void unlockFile() throws IOException JavaDoc {
113         if(fileLock != null) {
114             fileLock.release();
115             fileLock = null;
116         }
117     }
118
119     /**
120      * Closes the underlying RRD file if not already closed
121      * @throws IOException Thrown in case of I/O error
122      */

123     protected void finalize() throws IOException JavaDoc {
124         close();
125     }
126
127     /**
128      * Returns canonical path to the file on the disk.
129      * @param path File path
130      * @return Canonical file path
131      * @throws IOException Thrown in case of I/O error
132      */

133     public static String JavaDoc getCanonicalPath(String JavaDoc path) throws IOException JavaDoc {
134         return new File JavaDoc(path).getCanonicalPath();
135     }
136
137     /**
138      * Returns canonical path to the file on the disk.
139      * @return Canonical file path
140      * @throws IOException Thrown in case of I/O error
141      */

142     public String JavaDoc getCanonicalPath() throws IOException JavaDoc {
143         return RrdFileBackend.getCanonicalPath(getPath());
144     }
145
146     /**
147      * Writes bytes to the underlying RRD file on the disk
148      * @param offset Starting file offset
149      * @param b Bytes to be written.
150      * @throws IOException Thrown in case of I/O error
151      */

152     protected void write(long offset, byte[] b) throws IOException JavaDoc {
153         file.seek(offset);
154         file.write(b);
155     }
156
157     /**
158      * Reads a number of bytes from the RRD file on the disk
159      * @param offset Starting file offset
160      * @param b Buffer which receives bytes read from the file.
161      * @throws IOException Thrown in case of I/O error.
162      */

163     protected void read(long offset, byte[] b) throws IOException JavaDoc {
164         file.seek(offset);
165         if(file.read(b) != b.length) {
166             throw new IOException JavaDoc("Not enough bytes available in file " + getPath());
167         }
168     }
169
170     /**
171      * Returns RRD file length.
172      * @return File length.
173      * @throws IOException Thrown in case of I/O error.
174      */

175     public long getLength() throws IOException JavaDoc {
176         return file.length();
177     }
178
179     /**
180      * Sets length of the underlying RRD file. This method is called only once, immediately
181      * after a new RRD file gets created.
182      * @param length Length of the RRD file
183      * @throws IOException Thrown in case of I/O error.
184      */

185     protected void setLength(long length) throws IOException JavaDoc {
186         file.setLength(length);
187     }
188 }
189
Popular Tags