001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.lucene.store.jdbc.index;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.ArrayList;
022:
023: import org.apache.lucene.store.IndexOutput;
024: import org.apache.lucene.store.jdbc.JdbcDirectory;
025: import org.apache.lucene.store.jdbc.JdbcFileEntrySettings;
026:
027: /**
028: * An <code>IndexOutput</code> implemenation that stores all the data written to it in memory, and flushes it
029: * to the database when the output is closed.
030: * <p/>
031: * Useful for small file entries like the segment file.
032: *
033: * @author kimchy
034: */
035: public class RAMJdbcIndexOutput extends AbstractJdbcIndexOutput {
036:
037: private class RAMFile {
038: ArrayList buffers = new ArrayList();
039: long length;
040: }
041:
042: private class RAMInputStream extends InputStream {
043:
044: private long position;
045:
046: private int buffer;
047:
048: private int bufferPos;
049:
050: private long markedPosition;
051:
052: public synchronized void reset() throws IOException {
053: position = markedPosition;
054: }
055:
056: public boolean markSupported() {
057: return true;
058: }
059:
060: public void mark(int readlimit) {
061: this .markedPosition = position;
062: }
063:
064: public int read(byte[] dest, int destOffset, int len)
065: throws IOException {
066: if (position == file.length) {
067: return -1;
068: }
069: int remainder = (int) ((position + len > file.length) ? file.length
070: - position
071: : len);
072: long oldPosition = position;
073: while (remainder != 0) {
074: if (bufferPos == bufferSize) {
075: bufferPos = 0;
076: buffer++;
077: }
078: int bytesToCopy = bufferSize - bufferPos;
079: bytesToCopy = bytesToCopy >= remainder ? remainder
080: : bytesToCopy;
081: byte[] buf = (byte[]) file.buffers.get(buffer);
082: System.arraycopy(buf, bufferPos, dest, destOffset,
083: bytesToCopy);
084: destOffset += bytesToCopy;
085: position += bytesToCopy;
086: bufferPos += bytesToCopy;
087: remainder -= bytesToCopy;
088: }
089: return (int) (position - oldPosition);
090: }
091:
092: public int read() throws IOException {
093: if (position == file.length) {
094: return -1;
095: }
096: if (bufferPos == bufferSize) {
097: bufferPos = 0;
098: buffer++;
099: }
100: byte[] buf = (byte[]) file.buffers.get(buffer);
101: position++;
102: return buf[bufferPos++] & 0xFF;
103: }
104: }
105:
106: private RAMFile file;
107:
108: private int pointer = 0;
109:
110: public void configure(String name, JdbcDirectory jdbcDirectory,
111: JdbcFileEntrySettings settings) throws IOException {
112: super .configure(name, jdbcDirectory, settings);
113: this .file = new RAMFile();
114: this .name = name;
115: this .jdbcDirectory = jdbcDirectory;
116: }
117:
118: public void flushBuffer(byte[] src, int offset, int len) {
119: byte[] buffer;
120: int bufferPos = offset;
121: while (bufferPos != len) {
122: int bufferNumber = pointer / bufferSize;
123: int bufferOffset = pointer % bufferSize;
124: int bytesInBuffer = bufferSize - bufferOffset;
125: int remainInSrcBuffer = len - bufferPos;
126: int bytesToCopy = bytesInBuffer >= remainInSrcBuffer ? remainInSrcBuffer
127: : bytesInBuffer;
128:
129: if (bufferNumber == file.buffers.size()) {
130: buffer = new byte[bufferSize];
131: file.buffers.add(buffer);
132: } else {
133: buffer = (byte[]) file.buffers.get(bufferNumber);
134: }
135:
136: System.arraycopy(src, bufferPos, buffer, bufferOffset,
137: bytesToCopy);
138: bufferPos += bytesToCopy;
139: pointer += bytesToCopy;
140: }
141:
142: if (pointer > file.length)
143: file.length = pointer;
144: }
145:
146: protected InputStream openInputStream() throws IOException {
147: return new RAMInputStream();
148: }
149:
150: protected void doAfterClose() throws IOException {
151: file = null;
152: }
153:
154: public void seek(long pos) throws IOException {
155: super .seek(pos);
156: pointer = (int) pos;
157: }
158:
159: public long length() {
160: return file.length;
161: }
162:
163: public void flushToIndexOutput(IndexOutput indexOutput)
164: throws IOException {
165: super .flush();
166: if (file.buffers.size() == 0) {
167: return;
168: }
169: if (file.buffers.size() == 1) {
170: indexOutput.writeBytes((byte[]) file.buffers.get(0),
171: (int) file.length);
172: return;
173: }
174: int tempSize = file.buffers.size() - 1;
175: int i;
176: for (i = 0; i < tempSize; i++) {
177: indexOutput.writeBytes((byte[]) file.buffers.get(i),
178: bufferSize);
179: }
180: int leftOver = (int) (file.length % bufferSize);
181: if (leftOver == 0) {
182: indexOutput.writeBytes((byte[]) file.buffers.get(i),
183: bufferSize);
184: } else {
185: indexOutput.writeBytes((byte[]) file.buffers.get(i),
186: leftOver);
187: }
188: }
189: }
|