001: package com.quadcap.sql.file;
002:
003: /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.File;
042: import java.io.FileDescriptor;
043: import java.io.IOException;
044: import java.io.RandomAccessFile;
045:
046: import java.util.BitSet;
047:
048: import com.quadcap.util.collections.LongIterator;
049: import com.quadcap.util.collections.LongMap;
050:
051: import com.quadcap.util.Debug;
052: import com.quadcap.util.Util;
053:
054: import com.quadcap.sql.Version;
055:
056: /**
057: * Below the cache, this class handles the actual I/O to the underlying file.
058: * Block write operations are logged by this class.
059: *
060: * @author Stan Bailes
061: */
062: public class MemoryBlockStore extends BlockStore {
063: LongMap blocks;
064:
065: public MemoryBlockStore() {
066: }
067:
068: /**
069: * Initialize a new BlockStore object using the specified file and
070: * blocksize.
071: *
072: * @param file the underlying file.
073: * @param mode "r" for readonly access, otherwise "rw"
074: * @param blocksize the block size to use when creating the file.
075: * @param the synchronization object
076: */
077: public void init(File file, String mode, int blockSize, Object lock)
078: throws IOException {
079: this .blockSize = blockSize;
080: this .lock = lock;
081: this .blocks = new LongMap(8888);
082: createHeader(blockSize);
083: }
084:
085: /**
086: * Read a block into a buffer. If the specified block is beyond the
087: * current end of file, then grow the file
088: *
089: * @param blockNum the number of the block to read.
090: * @param buf the buffer into which the data is read.
091: */
092: public void read(long blockNum, byte[] buf, int off)
093: throws IOException {
094: //bug.println("read(" + blockNum + ")");
095: synchronized (lock) {
096: byte[] block = (byte[]) blocks.get(blockNum);
097: if (block == null) {
098: block = new byte[blockSize];
099: blocks.put(blockNum, block);
100: }
101: System.arraycopy(block, 0, buf, off, blockSize);
102: readCount++;
103: }
104: }
105:
106: /**
107: * Write a block from a buffer into the file.
108: *
109: * @param blockNum the number of the block to write.
110: * @param buf the buffer from which the data is written.
111: * @exception IOException if an I/O error occurs.
112: */
113: public void write(long blockNum, byte[] buf) throws IOException {
114: //bug.println("write(" + blockNum + "): \n" + Util.strBytes(buf, 0, 64));
115: synchronized (lock) {
116: byte[] block = (byte[]) blocks.get(blockNum);
117: boolean exists = (block != null);
118: if (!exists) {
119: block = new byte[blockSize];
120: blocks.put(blockNum, block);
121: }
122: if (log != null && !modified.get((int) blockNum)) {
123: modified.set((int) blockNum);
124: if (exists) {
125: log.saveBlock(blockNum);
126: }
127: }
128: System.arraycopy(buf, 0, block, 0, blockSize);
129: writeCount++;
130: //#ifdef DEBUG
131: if (Trace.bit(20)) {
132: Debug.println(toString() + ".write(" + blockNum + ")");
133: }
134: //#endif
135: }
136: }
137:
138: /**
139: * Restore a block image
140: */
141: public void restore(long blockNum, byte[] buf, int off)
142: throws IOException {
143: synchronized (lock) {
144: byte[] block = (byte[]) blocks.get(blockNum);
145: if (block == null) {
146: throw new IOException("No block to restore: "
147: + blockNum);
148: }
149: System.arraycopy(buf, off, block, 0, blockSize);
150: }
151:
152: }
153:
154: public void setLength(long length) throws IOException {
155: length /= blockSize;
156: LongIterator iter = blocks.keys();
157: while (iter.hasNext()) {
158: long blockNum = iter.nextLong();
159: if (blockNum >= length) {
160: iter.remove();
161: }
162: }
163: }
164:
165: private void createHeader(int blockSize) throws IOException {
166: this .blockSize = blockSize;
167: byte[] buf = newHeader(blockSize, 2);
168: blocks.put(0, buf);
169: }
170:
171: public boolean isEncrypted() {
172: return false;
173: }
174:
175: public void close() throws IOException {
176: }
177:
178: public void flush() throws IOException {
179: readCount = writeCount = 0;
180: }
181:
182: //#ifdef JDK14
183: public void setKey(com.quadcap.crypto.SymmetricKey key)
184: throws IOException {
185: throw new IOException("Not encrypted");
186: }
187:
188: //#endif
189:
190: //#ifdef DEBUG
191: public String toString() {
192: return "MemoryBlockStore()";
193: }
194:
195: public static String rw() {
196: return "(r=" + BlockStore.readCount + " w="
197: + BlockStore.writeCount + ")";
198: }
199:
200: //#endif
201:
202: }
|