KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > activemq > kaha > impl > async > ControlFile


1 /**
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one or more
4  * contributor license agreements. See the NOTICE file distributed with
5  * this work for additional information regarding copyright ownership.
6  * The ASF licenses this file to You under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.apache.activemq.kaha.impl.async;
19
20 import java.io.File JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.RandomAccessFile JavaDoc;
23 import java.nio.channels.FileLock JavaDoc;
24
25 import org.apache.activemq.util.ByteSequence;
26
27 /**
28  * Use to reliably store fixed sized state data. It stores the state in
29  * record that is versioned and repeated twice in the file so that a failure in the
30  * middle of the write of the first or second record do not not result in an unknown
31  * state.
32  *
33  * @version $Revision: 1.1 $
34  */

35 final public class ControlFile {
36     
37     private final static boolean DISABLE_FILE_LOCK = "true".equals(System.getProperty("java.nio.channels.FileLock.broken", "false"));
38     private final File JavaDoc file;
39
40     /** The File that holds the control data. */
41     private final RandomAccessFile JavaDoc randomAccessFile;
42     private final int maxRecordSize;
43
44     private long version=0;
45     private FileLock JavaDoc lock;
46     private boolean disposed;
47
48
49     public ControlFile(File JavaDoc file, int recordSize) throws IOException JavaDoc {
50         this.file = file;
51         this.maxRecordSize = recordSize+4;
52         randomAccessFile = new RandomAccessFile JavaDoc(file, "rw");
53     }
54
55     /**
56      * Locks the control file.
57      * @throws IOException
58      */

59     public void lock() throws IOException JavaDoc {
60         if( DISABLE_FILE_LOCK )
61             return;
62         
63         if( lock == null ) {
64             lock = randomAccessFile.getChannel().tryLock();
65             if (lock == null) {
66                 throw new IOException JavaDoc("Control file '"+file+"' could not be locked.");
67             }
68         }
69     }
70
71     /**
72      * Un locks the control file.
73      *
74      * @throws IOException
75      */

76     public void unlock() throws IOException JavaDoc {
77         if( DISABLE_FILE_LOCK )
78             return;
79         
80         if (lock != null) {
81             lock.release();
82             lock = null;
83         }
84     }
85   
86     public void dispose() {
87         if( disposed )
88             return;
89         disposed=true;
90         try {
91             unlock();
92         } catch (IOException JavaDoc e) {
93         }
94         try {
95             randomAccessFile.close();
96         } catch (IOException JavaDoc e) {
97         }
98     }
99
100     synchronized public ByteSequence load() throws IOException JavaDoc {
101         long l = randomAccessFile.length();
102         if( l < maxRecordSize ) {
103             return null;
104         }
105         
106         randomAccessFile.seek(0);
107         long v1 = randomAccessFile.readLong();
108         randomAccessFile.seek(maxRecordSize+8);
109         long v1check = randomAccessFile.readLong();
110         
111         randomAccessFile.seek(maxRecordSize+16);
112         long v2 = randomAccessFile.readLong();
113         randomAccessFile.seek((maxRecordSize*2)+24);
114         long v2check = randomAccessFile.readLong();
115         
116         byte[] data=null;
117         if( v2 == v2check ) {
118             version = v2;
119             randomAccessFile.seek(maxRecordSize+24);
120             int size = randomAccessFile.readInt();
121             data = new byte[size];
122             randomAccessFile.readFully(data);
123         } else if ( v1 == v1check ){
124             version = v1;
125             randomAccessFile.seek(maxRecordSize+8);
126             int size = randomAccessFile.readInt();
127             data = new byte[size];
128             randomAccessFile.readFully(data);
129         } else {
130             // Bummer.. Both checks are screwed. we don't know
131
// if any of the two buffer are ok. This should
132
// only happen is data got corrupted.
133
throw new IOException JavaDoc("Control data corrupted.");
134         }
135         return new ByteSequence(data,0,data.length);
136     }
137     
138     public void store(ByteSequence data, boolean sync) throws IOException JavaDoc {
139         
140         version++;
141         randomAccessFile.setLength((maxRecordSize*2)+32);
142         randomAccessFile.seek(0);
143         
144         // Write the first copy of the control data.
145
randomAccessFile.writeLong(version);
146         randomAccessFile.writeInt(data.getLength());
147         randomAccessFile.write(data.getData());
148         randomAccessFile.writeLong(version);
149
150         // Write the second copy of the control data.
151
randomAccessFile.writeLong(version);
152         randomAccessFile.writeInt(data.getLength());
153         randomAccessFile.write(data.getData());
154         randomAccessFile.writeLong(version);
155         
156         if( sync ) {
157             randomAccessFile.getFD().sync();
158         }
159     }
160
161 }
162
Popular Tags