KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > persist > ScaledRAFileNIO


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb.persist;
33
34 import java.io.IOException JavaDoc;
35 import java.io.RandomAccessFile JavaDoc;
36 import java.nio.MappedByteBuffer JavaDoc;
37 import java.nio.channels.FileChannel JavaDoc;
38
39 import org.hsqldb.Database;
40 import org.hsqldb.Trace;
41 import org.hsqldb.lib.SimpleLog;
42
43 /**
44  * New NIO version of ScaledRAFile. This class is used only for storing a CACHED
45  * TABLE .data file and cannot be used for TEXT TABLE source files.
46  *
47  * Due to various issues with java.nio classes, this class will use a mapped
48  * channel of fixed size. After reaching this size, the file and channel are
49  * closed.
50  *
51  * @author fredt@users
52  * @version 1.8.0.5
53  * @since 1.8.0.5
54  */

55 class ScaledRAFileNIO implements ScaledRAInterface {
56
57     private final boolean readOnly;
58     private final long bufferLength;
59     private RandomAccessFile JavaDoc file;
60     private MappedByteBuffer JavaDoc buffer;
61     private FileChannel JavaDoc channel;
62     private boolean bufferModified;
63     private SimpleLog appLog;
64     private final static String JavaDoc JVM_ERROR = "JVM threw unsupported Exception";
65
66     ScaledRAFileNIO(Database database, String JavaDoc name, boolean readOnly,
67                     int bufferLength) throws Throwable JavaDoc {
68
69         long fileLength;
70
71         if (bufferLength < 1 << 18) {
72             bufferLength = 1 << 18;
73         }
74
75         try {
76             file = new RandomAccessFile JavaDoc(name, readOnly ? "r"
77                                                        : "rw");
78         } catch (Throwable JavaDoc e) {
79             throw e;
80         }
81
82         try {
83             fileLength = file.length();
84         } catch (Throwable JavaDoc e) {
85             file.close();
86
87             throw e;
88         }
89
90         if (fileLength > ScaledRAFile.MAX_NIO_LENGTH) {
91             file.close();
92
93             throw new IOException JavaDoc("length exceeds nio limit");
94         }
95
96         if (bufferLength < fileLength) {
97             bufferLength = (int) fileLength;
98         }
99
100         bufferLength = newNIOBufferSize(bufferLength);
101
102         if (readOnly) {
103             bufferLength = (int) fileLength;
104         }
105
106         if (fileLength < bufferLength) {
107             try {
108                 file.seek(bufferLength - 1);
109                 file.writeByte(0);
110                 file.getFD().sync();
111                 file.close();
112
113                 file = new RandomAccessFile JavaDoc(name, readOnly ? "r"
114                                                            : "rw");
115             } catch (Throwable JavaDoc e) {
116                 file.close();
117
118                 throw e;
119             }
120         }
121
122         this.appLog = database.logger.appLog;
123         this.readOnly = readOnly;
124         this.bufferLength = bufferLength;
125         this.channel = file.getChannel();
126
127         try {
128             buffer = channel.map(readOnly ? FileChannel.MapMode.READ_ONLY
129                                           : FileChannel.MapMode.READ_WRITE, 0,
130                                           bufferLength);
131
132             Trace.printSystemOut("NIO file instance created. mode: "
133                                  + readOnly);
134
135             if (!readOnly) {
136                 long tempSize = bufferLength - fileLength;
137
138                 if (tempSize > 1 << 18) {
139                     tempSize = 1 << 18;
140                 }
141
142                 byte[] temp = new byte[(int) tempSize];
143
144                 try {
145                     long pos = fileLength;
146
147                     for (; pos < bufferLength - tempSize; pos += tempSize) {
148                         buffer.position((int) pos);
149                         buffer.put(temp, 0, temp.length);
150                     }
151
152                     buffer.position((int) pos);
153                     buffer.put(temp, 0, (int) (bufferLength - pos));
154                     buffer.force();
155                 } catch (Throwable JavaDoc t) {
156                     appLog.logContext(t, JVM_ERROR + " " + "length: "
157                                       + bufferLength);
158                 }
159
160                 buffer.position(0);
161             }
162         } catch (Throwable JavaDoc e) {
163             Trace.printSystemOut("NIO constructor failed: " + bufferLength);
164
165             buffer = null;
166             channel = null;
167
168             file.close();
169             System.gc();
170
171             throw e;
172         }
173     }
174
175     public long length() throws IOException JavaDoc {
176
177         try {
178             return file.length();
179         } catch (IOException JavaDoc e) {
180             appLog.logContext(e, "nio");
181
182             throw e;
183         } catch (Throwable JavaDoc e) {
184             appLog.logContext(e, JVM_ERROR);
185
186             throw new IOException JavaDoc(e.toString());
187         }
188     }
189
190     public void seek(long newPos) throws IOException JavaDoc {
191
192         try {
193             buffer.position((int) newPos);
194         } catch (IllegalArgumentException JavaDoc e) {
195             appLog.logContext(e, "nio");
196
197             throw new IOException JavaDoc(e.toString());
198         } catch (Throwable JavaDoc e) {
199             appLog.logContext(e, JVM_ERROR);
200
201             throw new IOException JavaDoc(e.toString());
202         }
203     }
204
205     public long getFilePointer() throws IOException JavaDoc {
206
207         try {
208             return buffer.position();
209         } catch (Throwable JavaDoc e) {
210             appLog.logContext(e, JVM_ERROR);
211
212             throw new IOException JavaDoc(e.toString());
213         }
214     }
215
216     public int read() throws IOException JavaDoc {
217
218         try {
219             return buffer.get();
220         } catch (Throwable JavaDoc e) {
221             appLog.logContext(e, JVM_ERROR);
222
223             throw new IOException JavaDoc(e.toString());
224         }
225     }
226
227     public void read(byte[] b, int offset, int length) throws IOException JavaDoc {
228
229         try {
230             buffer.get(b, offset, length);
231         } catch (Throwable JavaDoc e) {
232             appLog.logContext(e, JVM_ERROR);
233
234             throw new IOException JavaDoc(e.toString());
235         }
236     }
237
238     public int readInt() throws IOException JavaDoc {
239
240         try {
241             return buffer.getInt();
242         } catch (Throwable JavaDoc e) {
243             appLog.logContext(e, JVM_ERROR);
244
245             throw new IOException JavaDoc(e.toString());
246         }
247     }
248
249     public long readLong() throws IOException JavaDoc {
250
251         try {
252             return buffer.getLong();
253         } catch (Throwable JavaDoc e) {
254             appLog.logContext(e, JVM_ERROR);
255
256             throw new IOException JavaDoc(e.toString());
257         }
258     }
259
260     public void write(byte[] b, int offset, int len) throws IOException JavaDoc {
261
262         try {
263             bufferModified = true;
264
265             buffer.put(b, offset, len);
266         } catch (Throwable JavaDoc e) {
267             appLog.logContext(e, JVM_ERROR);
268
269             throw new IOException JavaDoc(e.toString());
270         }
271     }
272
273     public void writeInt(int i) throws IOException JavaDoc {
274
275         try {
276             bufferModified = true;
277
278             buffer.putInt(i);
279         } catch (Throwable JavaDoc e) {
280             appLog.logContext(e, JVM_ERROR);
281
282             throw new IOException JavaDoc(e.toString());
283         }
284     }
285
286     public void writeLong(long i) throws IOException JavaDoc {
287
288         try {
289             bufferModified = true;
290
291             buffer.putLong(i);
292         } catch (Throwable JavaDoc e) {
293             appLog.logContext(e, JVM_ERROR);
294
295             throw new IOException JavaDoc(e.toString());
296         }
297     }
298
299     public void close() throws IOException JavaDoc {
300
301         try {
302             Trace.printSystemOut("NIO close() start - fileLength = "
303                                  + bufferLength);
304
305             if (buffer != null && bufferModified) {
306                 try {
307                     buffer.force();
308                 } catch (Throwable JavaDoc t) {
309                     try {
310                         buffer.force();
311                     } catch (Throwable JavaDoc t1) {
312                         appLog.logContext(t, JVM_ERROR + " " + "length: "
313                                           + bufferLength);
314                     }
315                 }
316             }
317
318             buffer = null;
319             channel = null;
320
321             file.close();
322             System.gc();
323         } catch (Throwable JavaDoc e) {
324             appLog.logContext(e, "length: " + bufferLength);
325
326             throw new IOException JavaDoc(e.toString());
327         }
328     }
329
330     public boolean isReadOnly() {
331         return readOnly;
332     }
333
334     public boolean wasNio() {
335         return true;
336     }
337
338     public boolean canAccess(int length) {
339         return buffer.position() + length <= bufferLength;
340     }
341
342     public boolean canSeek(long position) {
343         return position <= bufferLength;
344     }
345
346     public Database getDatabase() {
347         return null;
348     }
349
350     static int newNIOBufferSize(int newSize) {
351
352         int bufSize = 0;
353
354         for (int scale = 20; scale < 30; scale++) {
355             bufSize = 1 << scale;
356
357             if (bufSize >= newSize) {
358                 break;
359             }
360         }
361
362         return bufSize;
363     }
364 }
365
Popular Tags