001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.util;
018
019import java.io.File;
020import java.io.FileDescriptor;
021import java.io.FileNotFoundException;
022import java.io.IOException;
023import java.io.RandomAccessFile;
024import java.nio.channels.FileChannel;
025
026public class RecoverableRandomAccessFile implements java.io.DataOutput, java.io.DataInput, java.io.Closeable {
027
028    private static final boolean SKIP_METADATA_UPDATE =
029        Boolean.getBoolean("org.apache.activemq.kahaDB.files.skipMetadataUpdate");
030
031    RandomAccessFile raf;
032    File file;
033    String mode;
034    final boolean isSkipMetadataUpdate;
035
036    public RecoverableRandomAccessFile(File file, String mode, boolean skipMetadataUpdate) throws FileNotFoundException {
037        this.file = file;
038        this.mode = mode;
039        raf = new RandomAccessFile(file, mode);
040        isSkipMetadataUpdate = skipMetadataUpdate;
041    }
042
043    public RecoverableRandomAccessFile(File file, String mode) throws FileNotFoundException {
044        this(file, mode, SKIP_METADATA_UPDATE);
045    }
046
047    public RecoverableRandomAccessFile(String name, String mode) throws FileNotFoundException {
048        this(new File(name), mode);
049    }
050
051    public RandomAccessFile getRaf() throws IOException {
052        if (raf == null) {
053            raf = new RandomAccessFile(file, mode);
054        }
055        return raf;
056    }
057
058    protected void handleException() throws IOException {
059        try {
060            if (raf != null) {
061                raf.close();
062            }
063        } catch (Throwable ignore) {
064        } finally {
065            raf = null;
066        }
067    }
068
069    @Override
070    public void close() throws IOException {
071        if (raf != null) {
072            raf.close();
073        }
074    }
075
076    @Override
077    public void readFully(byte[] bytes) throws IOException {
078        try {
079            getRaf().readFully(bytes);
080        } catch (IOException ioe) {
081            handleException();
082            throw ioe;
083        }
084    }
085
086    @Override
087    public void readFully(byte[] bytes, int i, int i2) throws IOException {
088        try {
089            getRaf().readFully(bytes, i, i2);
090        } catch (IOException ioe) {
091            handleException();
092            throw ioe;
093        }
094    }
095
096    @Override
097    public int skipBytes(int i) throws IOException {
098        try {
099            return getRaf().skipBytes(i);
100        } catch (IOException ioe) {
101            handleException();
102            throw ioe;
103        }
104    }
105
106    @Override
107    public boolean readBoolean() throws IOException {
108        try {
109            return getRaf().readBoolean();
110        } catch (IOException ioe) {
111            handleException();
112            throw ioe;
113        }
114    }
115
116    @Override
117    public byte readByte() throws IOException {
118        try {
119            return getRaf().readByte();
120        } catch (IOException ioe) {
121            handleException();
122            throw ioe;
123        }
124    }
125
126    @Override
127    public int readUnsignedByte() throws IOException {
128        try {
129            return getRaf().readUnsignedByte();
130        } catch (IOException ioe) {
131            handleException();
132            throw ioe;
133        }
134    }
135
136    @Override
137    public short readShort() throws IOException {
138        try {
139            return getRaf().readShort();
140        } catch (IOException ioe) {
141            handleException();
142            throw ioe;
143        }
144    }
145
146    @Override
147    public int readUnsignedShort() throws IOException {
148        try {
149            return getRaf().readUnsignedShort();
150        } catch (IOException ioe) {
151            handleException();
152            throw ioe;
153        }
154    }
155
156    @Override
157    public char readChar() throws IOException {
158        try {
159            return getRaf().readChar();
160        } catch (IOException ioe) {
161            handleException();
162            throw ioe;
163        }
164    }
165
166    @Override
167    public int readInt() throws IOException {
168        try {
169            return getRaf().readInt();
170        } catch (IOException ioe) {
171            handleException();
172            throw ioe;
173        }
174    }
175
176    @Override
177    public long readLong() throws IOException {
178        try {
179            return getRaf().readLong();
180        } catch (IOException ioe) {
181            handleException();
182            throw ioe;
183        }
184    }
185
186    @Override
187    public float readFloat() throws IOException {
188        try {
189            return getRaf().readFloat();
190        } catch (IOException ioe) {
191            handleException();
192            throw ioe;
193        }
194    }
195
196    @Override
197    public double readDouble() throws IOException {
198        try {
199            return getRaf().readDouble();
200        } catch (IOException ioe) {
201            handleException();
202            throw ioe;
203        }
204    }
205
206    @Override
207    public String readLine() throws IOException {
208        try {
209            return getRaf().readLine();
210        } catch (IOException ioe) {
211            handleException();
212            throw ioe;
213        }
214    }
215
216    @Override
217    public String readUTF() throws IOException {
218        try {
219            return getRaf().readUTF();
220        } catch (IOException ioe) {
221            handleException();
222            throw ioe;
223        }
224    }
225
226    @Override
227    public void write(int i) throws IOException {
228        try {
229            getRaf().write(i);
230        } catch (IOException ioe) {
231            handleException();
232            throw ioe;
233        }
234    }
235
236    @Override
237    public void write(byte[] bytes) throws IOException {
238        try {
239            getRaf().write(bytes);
240        } catch (IOException ioe) {
241            handleException();
242            throw ioe;
243        }
244    }
245
246    @Override
247    public void write(byte[] bytes, int i, int i2) throws IOException {
248        try {
249            getRaf().write(bytes, i, i2);
250        } catch (IOException ioe) {
251            handleException();
252            throw ioe;
253        }
254    }
255
256    @Override
257    public void writeBoolean(boolean b) throws IOException {
258        try {
259            getRaf().writeBoolean(b);
260        } catch (IOException ioe) {
261            handleException();
262            throw ioe;
263        }
264    }
265
266    @Override
267    public void writeByte(int i) throws IOException {
268        try {
269            getRaf().writeByte(i);
270        } catch (IOException ioe) {
271            handleException();
272            throw ioe;
273        }
274    }
275
276    @Override
277    public void writeShort(int i) throws IOException {
278        try {
279            getRaf().writeShort(i);
280        } catch (IOException ioe) {
281            handleException();
282            throw ioe;
283        }
284    }
285
286    @Override
287    public void writeChar(int i) throws IOException {
288        try {
289            getRaf().writeChar(i);
290        } catch (IOException ioe) {
291            handleException();
292            throw ioe;
293        }
294    }
295
296    @Override
297    public void writeInt(int i) throws IOException {
298        try {
299            getRaf().writeInt(i);
300        } catch (IOException ioe) {
301            handleException();
302            throw ioe;
303        }
304    }
305
306    @Override
307    public void writeLong(long l) throws IOException {
308        try {
309            getRaf().writeLong(l);
310        } catch (IOException ioe) {
311            handleException();
312            throw ioe;
313        }
314    }
315
316    @Override
317    public void writeFloat(float v) throws IOException {
318        try {
319            getRaf().writeFloat(v);
320        } catch (IOException ioe) {
321            handleException();
322            throw ioe;
323        }
324    }
325
326    @Override
327    public void writeDouble(double v) throws IOException {
328        try {
329            getRaf().writeDouble(v);
330        } catch (IOException ioe) {
331            handleException();
332            throw ioe;
333        }
334    }
335
336    @Override
337    public void writeBytes(String s) throws IOException {
338        try {
339            getRaf().writeBytes(s);
340        } catch (IOException ioe) {
341            handleException();
342            throw ioe;
343        }
344    }
345
346    @Override
347    public void writeChars(String s) throws IOException {
348        try {
349            getRaf().writeChars(s);
350        } catch (IOException ioe) {
351            handleException();
352            throw ioe;
353        }
354    }
355
356    @Override
357    public void writeUTF(String s) throws IOException {
358        try {
359            getRaf().writeUTF(s);
360        } catch (IOException ioe) {
361            handleException();
362            throw ioe;
363        }
364    }
365
366
367    //RAF methods
368    public long length() throws IOException {
369        try {
370            return getRaf().length();
371        } catch (IOException ioe) {
372            handleException();
373            throw ioe;
374        }
375    }
376
377    public void setLength(long length) throws IOException {
378        throw new IllegalStateException("File size is pre allocated");
379    }
380
381    public void seek(long pos) throws IOException {
382        try {
383            getRaf().seek(pos);
384        } catch (IOException ioe) {
385            handleException();
386            throw ioe;
387        }
388    }
389
390    public FileDescriptor getFD() throws IOException {
391        try {
392            return getRaf().getFD();
393        } catch (IOException ioe) {
394            handleException();
395            throw ioe;
396        }
397    }
398
399    public void sync() throws IOException {
400        try {
401            getRaf().getChannel().force(!isSkipMetadataUpdate);;
402        } catch (IOException ioe) {
403            handleException();
404            throw ioe;
405        }
406    }
407
408    public FileChannel getChannel() throws IOException {
409        try {
410            return getRaf().getChannel();
411        } catch (IOException ioe) {
412            handleException();
413            throw ioe;
414        }
415    }
416
417    public int read(byte[] b, int off, int len) throws IOException {
418        try {
419            return getRaf().read(b, off, len);
420        } catch (IOException ioe) {
421            handleException();
422            throw ioe;
423        }
424    }
425
426    public int read(byte[] b) throws IOException {
427        try {
428            return getRaf().read(b);
429        } catch (IOException ioe) {
430            handleException();
431            throw ioe;
432        }
433    }
434}