001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.store;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.sql.SQLException;
011:
012: import org.h2.constant.SysProperties;
013: import org.h2.engine.Constants;
014: import org.h2.message.Message;
015: import org.h2.tools.CompressTool;
016:
017: /**
018: * An input stream that is backed by a file store.
019: */
020: public class FileStoreInputStream extends InputStream {
021:
022: private FileStore store;
023: private DataPage page;
024: private int remainingInBuffer;
025: private CompressTool compress;
026: private boolean endOfFile;
027: private boolean alwaysClose;
028:
029: public FileStoreInputStream(FileStore store, DataHandler handler,
030: boolean compression, boolean alwaysClose)
031: throws SQLException {
032: this .store = store;
033: this .alwaysClose = alwaysClose;
034: if (compression) {
035: compress = CompressTool.getInstance();
036: }
037: page = DataPage.create(handler, Constants.FILE_BLOCK_SIZE);
038: try {
039: if (store.length() <= FileStore.HEADER_LENGTH) {
040: close();
041: } else {
042: fillBuffer();
043: }
044: } catch (IOException e) {
045: throw Message.convertIOException(e, store.name);
046: }
047: }
048:
049: public int available() {
050: return remainingInBuffer <= 0 ? 0 : remainingInBuffer;
051: }
052:
053: public int read(byte[] buff) throws IOException {
054: return read(buff, 0, buff.length);
055: }
056:
057: public int read(byte[] b, int off, int len) throws IOException {
058: if (len == 0) {
059: return 0;
060: }
061: int read = 0;
062: while (len > 0) {
063: int r = readBlock(b, off, len);
064: if (r < 0) {
065: break;
066: }
067: read += r;
068: off += r;
069: len -= r;
070: }
071: return read == 0 ? -1 : read;
072: }
073:
074: public int readBlock(byte[] buff, int off, int len)
075: throws IOException {
076: fillBuffer();
077: if (endOfFile) {
078: return -1;
079: }
080: int l = Math.min(remainingInBuffer, len);
081: page.read(buff, off, l);
082: remainingInBuffer -= l;
083: return l;
084: }
085:
086: private void fillBuffer() throws IOException {
087: if (remainingInBuffer > 0 || endOfFile) {
088: return;
089: }
090: page.reset();
091: try {
092: store.openFile();
093: if (store.length() == store.getFilePointer()) {
094: close();
095: return;
096: }
097: store.readFully(page.getBytes(), 0,
098: Constants.FILE_BLOCK_SIZE);
099: } catch (SQLException e) {
100: throw Message.convertToIOException(e);
101: }
102: page.reset();
103: remainingInBuffer = page.readInt();
104: if (remainingInBuffer < 0) {
105: close();
106: return;
107: }
108: page.checkCapacity(remainingInBuffer);
109: // get the length to read
110: if (compress != null) {
111: page.checkCapacity(page.getIntLen());
112: page.readInt();
113: }
114: page.setPos(page.length() + remainingInBuffer);
115: page.fillAligned();
116: int len = page.length() - Constants.FILE_BLOCK_SIZE;
117: page.reset();
118: page.readInt();
119: try {
120: store.readFully(page.getBytes(), Constants.FILE_BLOCK_SIZE,
121: len);
122: page.reset();
123: page.readInt();
124: if (compress != null) {
125: int uncompressed = page.readInt();
126: byte[] buff = new byte[remainingInBuffer];
127: page.read(buff, 0, remainingInBuffer);
128: page.reset();
129: page.checkCapacity(uncompressed);
130: compress.expand(buff, page.getBytes(), 0);
131: remainingInBuffer = uncompressed;
132: }
133: } catch (SQLException e) {
134: throw Message.convertToIOException(e);
135: }
136: if (alwaysClose) {
137: store.closeFile();
138: }
139: }
140:
141: public void close() throws IOException {
142: if (store != null) {
143: try {
144: store.close();
145: endOfFile = true;
146: } finally {
147: store = null;
148: }
149: }
150: }
151:
152: protected void finalize() {
153: if (!SysProperties.runFinalize) {
154: return;
155: }
156: try {
157: close();
158: } catch (IOException e) {
159: // ignore
160: }
161: }
162:
163: public int read() throws IOException {
164: fillBuffer();
165: if (endOfFile) {
166: return -1;
167: }
168: int i = page.readByte() & 0xff;
169: remainingInBuffer--;
170: return i;
171: }
172:
173: }
|