KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > file > BlockStore


1 package com.quadcap.sql.file;
2
3 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.File JavaDoc;
42 import java.io.FileDescriptor JavaDoc;
43 import java.io.IOException JavaDoc;
44 import java.io.RandomAccessFile JavaDoc;
45
46 import java.util.BitSet JavaDoc;
47
48 import com.quadcap.util.Debug;
49 import com.quadcap.util.Util;
50
51 import com.quadcap.sql.Version;
52
53 /**
54  * Below the cache, this class handles the actual I/O to the underlying file.
55  * Block write operations are logged by this class.
56  *
57  * @author Stan Bailes
58  */

59 public class BlockStore {
60     File JavaDoc file;
61     FileRandomAccess fra;
62     boolean readOnly;
63     Log log;
64     int blockSize;
65     BitSet JavaDoc modified = new BitSet JavaDoc();
66     Object JavaDoc lock;
67     boolean encrypted = false;
68     boolean isTempFile = false;
69
70     /**
71      * Create a new BlockStore object using the specified file and
72      * blocksize.
73      *
74      * @param file the underlying file.
75      * @param mode "r" for readonly access, otherwise "rw"
76      * @param blocksize the block size to use when creating the file.
77      * @param the synchronization object
78      */

79     public BlockStore() {
80     }
81
82     public String JavaDoc getName() {
83         return file == null ? "null" : file.getName();
84     }
85
86     public void init(File JavaDoc file, String JavaDoc mode, int blockSize, Object JavaDoc lock)
87         throws IOException JavaDoc
88     {
89     this.file = file;
90         boolean exists = file.exists();
91     RandomAccessFile JavaDoc ra = new RandomAccessFile JavaDoc(file.getAbsolutePath(), mode);
92         this.fra = new FileRandomAccess(ra, 1024L * 1024L * 1024L * 1024L);
93     this.readOnly = mode.equalsIgnoreCase("r");
94         this.lock = lock;
95         if (!exists) {
96             createHeader(blockSize);
97         } else {
98             readHeader();
99         }
100         isTempFile = !(file.getPath().endsWith("datafile"));
101     }
102
103     /**
104      * Specify the log used for recovery operations.
105      */

106     public void setLog(Log log) { this.log = log; }
107
108     /**
109      * Return the logger
110      */

111     public Log getLog() { return log; }
112
113     /**
114      * Return the block size of this store.
115      */

116     public int blockSize() { return blockSize; }
117
118     /**
119      * Return the underlying file
120      */

121     public File JavaDoc getFile() { return file; }
122
123     /**
124      * Read a block into a buffer. If the specified block is beyond the
125      * current end of file, then grow the file
126      *
127      * @param blockNum the number of the block to read.
128      * @param buf the buffer into which the data is read.
129      */

130     public void read(long blockNum, byte[] buf) throws IOException JavaDoc {
131         read(blockNum, buf, 0);
132     }
133     
134     public void read(long blockNum, byte[] buf, int off)
135     throws IOException JavaDoc
136     {
137         synchronized (lock) {
138             readCount++;
139             fra.read(blockNum * blockSize, buf, off, blockSize);
140         }
141     }
142
143     public static int writeCount = 0;
144     public static int readCount = 0;
145     /**
146      * Write a block from a buffer into the file.
147      *
148      * @param blockNum the number of the block to write.
149      * @param buf the buffer from which the data is written.
150      * @exception IOException if an I/O error occurs.
151      */

152     public void write(long blockNum, byte[] buf)
153     throws IOException JavaDoc
154     {
155         synchronized (lock) {
156             writeCount++;
157             if (readOnly) {
158                 throw new IOException JavaDoc("Attempt to write readonly file: " +
159                                       file.getName());
160             }
161             long pos = blockNum * blockSize;
162             if (log != null && !modified.get((int)blockNum)) {
163                 modified.set((int)blockNum);
164                 if (pos < fra.size()) {
165                     log.saveBlock(blockNum);
166                 }
167             }
168             //#ifdef DEBUG
169
if (Trace.bit(20)) {
170                 Debug.println(toString() + ".write(" + blockNum + "," +
171                               Block.signature(buf) + ") " + Util.stackTrace());
172             }
173             //#endif
174
fra.write(blockNum * blockSize, buf, 0, buf.length);
175         }
176     }
177
178     /**
179      * Restore a block image
180      */

181     public void restore(long blockNum, byte[] buf, int off)
182         throws IOException JavaDoc
183     {
184         synchronized (lock) {
185             //#ifdef DEBUG
186
if (Trace.bit(20)) {
187                 Debug.println(toString() + ".restore(" + blockNum + "," +
188                               Block.signature(buf, off, blockSize) + ")");
189             }
190             //#endif
191
fra.write(blockNum * blockSize, buf, off, blockSize);
192         }
193         
194     }
195     
196     public void clearModified() throws IOException JavaDoc {
197     modified = new BitSet JavaDoc();
198         if (log != null) log.resetBlocks();
199     }
200
201
202     public void setLength(long length) throws IOException JavaDoc {
203     if (readOnly) {
204         throw new IOException JavaDoc("Attempt to write readonly file: " +
205                   file.getName());
206     }
207     fra.resize(length);
208     }
209
210     public boolean isEncrypted() {
211         return encrypted;
212     }
213     
214     private void readHeader() throws IOException JavaDoc {
215         byte[] buf = new byte[32];
216         fra.read(0, buf, 0, buf.length);
217         int v = ((buf[0] & 0xff) << 8) + (buf[1] & 0xff);
218         switch (v) {
219         case 0x040c: // QED.
220
encrypted = false;
221             break;
222         case 0x0e0c: // Encrypted QED.
223
encrypted = true;
224             break;
225         default:
226             throw new IOException JavaDoc("BlockFile: bad magic");
227         }
228         // XXX This is hokey. We've tied database versions to the
229
// XXX product version numbers somehow, so we complain about
230
// XXX incompatibility based on the wrong version. Need
231
// XXX BlockFile, Database, versions....
232
if (buf[2] != Version.majorVersion) {
233             throw new IOException JavaDoc("BlockFile: bad version (" +
234                                   (int)buf[2] + "." + (int)buf[3] +
235                                   " vs " +
236                                   Version.majorVersion + "." +
237                                   Version.minorVersion + ")");
238         }
239         this.blockSize = ByteUtil.getInt(buf, BlockFile.oBLOCKSIZE);
240     }
241
242     private void createHeader(int blockSize) throws IOException JavaDoc {
243         this.blockSize = blockSize;
244         byte[] buf = newHeader(blockSize, 2);
245         fra.write(0, buf, 0, buf.length);
246     }
247
248     protected final byte[] newHeader(int blockSize, long lastBlock) {
249     byte[] buf = new byte[blockSize];
250     for (int i = 0; i < blockSize; i++) buf[i] = (byte)0;
251     buf[0] = 0x4; buf[1] = 0xc; // magic
252
buf[2] = Version.majorVersion;
253         buf[3] = Version.minorVersion;
254     ByteUtil.putInt(buf, BlockFile.oBLOCKSIZE, blockSize);
255     ByteUtil.putLong(buf, BlockFile.oLASTBLOCK, lastBlock); // allocated one block
256
return buf;
257     }
258
259     public void close() throws IOException JavaDoc {
260         try {
261             if (fra != null) fra.close();
262         } finally {
263             fra = null;
264         }
265     }
266
267     public void flush() throws IOException JavaDoc {
268         try {
269             fra.flush();
270             readCount = writeCount = 0;
271         } catch (Throwable JavaDoc t) {}
272     }
273
274     //#ifdef JDK14
275
public void setKey(com.quadcap.crypto.SymmetricKey key)
276         throws IOException JavaDoc
277     {
278         throw new IOException JavaDoc("Not encrypted");
279     }
280     //#endif
281

282     //#ifdef DEBUG
283
public String JavaDoc toString() {
284         return "BlockStore(" + file.getPath() + ")";
285     }
286
287     public static String JavaDoc rw() {
288         return "(r=" + BlockStore.readCount +
289             " w=" + BlockStore.writeCount + ")";
290     }
291                    
292     //#endif
293

294 }
295
Popular Tags