/* * Copyright 2004-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.lucene.store.jdbc.index; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.jdbc.JdbcDirectory; import org.apache.lucene.store.jdbc.JdbcFileEntrySettings; /** * An <code>IndexOutput</code> implemenation that stores all the data written to it in memory, and flushes it * to the database when the output is closed. * <p/> * Useful for small file entries like the segment file. * * @author kimchy */ public class RAMJdbcIndexOutput extends AbstractJdbcIndexOutput { private class RAMFile { ArrayList buffers = new ArrayList(); long length; } private class RAMInputStream extends InputStream { private long position; private int buffer; private int bufferPos; private long markedPosition; public synchronized void reset() throws IOException { position = markedPosition; } public boolean markSupported() { return true; } public void mark(int readlimit) { this.markedPosition = position; } public int read(byte[] dest, int destOffset, int len) throws IOException { if (position == file.length) { return -1; } int remainder = (int) ((position + len > file.length) ? file.length - position : len); long oldPosition = position; while (remainder != 0) { if (bufferPos == bufferSize) { bufferPos = 0; buffer++; } int bytesToCopy = bufferSize - bufferPos; bytesToCopy = bytesToCopy >= remainder ? remainder : bytesToCopy; byte[] buf = (byte[]) file.buffers.get(buffer); System.arraycopy(buf, bufferPos, dest, destOffset, bytesToCopy); destOffset += bytesToCopy; position += bytesToCopy; bufferPos += bytesToCopy; remainder -= bytesToCopy; } return (int) (position - oldPosition); } public int read() throws IOException { if (position == file.length) { return -1; } if (bufferPos == bufferSize) { bufferPos = 0; buffer++; } byte[] buf = (byte[]) file.buffers.get(buffer); position++; return buf[bufferPos++] & 0xFF; } } private RAMFile file; private int pointer = 0; public void configure(String name, JdbcDirectory jdbcDirectory, JdbcFileEntrySettings settings) throws IOException { super.configure(name, jdbcDirectory, settings); this.file = new RAMFile(); this.name = name; this.jdbcDirectory = jdbcDirectory; } public void flushBuffer(byte[] src, int offset, int len) { byte[] buffer; int bufferPos = offset; while (bufferPos != len) { int bufferNumber = pointer / bufferSize; int bufferOffset = pointer % bufferSize; int bytesInBuffer = bufferSize - bufferOffset; int remainInSrcBuffer = len - bufferPos; int bytesToCopy = bytesInBuffer >= remainInSrcBuffer ? remainInSrcBuffer : bytesInBuffer; if (bufferNumber == file.buffers.size()) { buffer = new byte[bufferSize]; file.buffers.add(buffer); } else { buffer = (byte[]) file.buffers.get(bufferNumber); } System.arraycopy(src, bufferPos, buffer, bufferOffset, bytesToCopy); bufferPos += bytesToCopy; pointer += bytesToCopy; } if (pointer > file.length) file.length = pointer; } protected InputStream openInputStream() throws IOException { return new RAMInputStream(); } protected void doAfterClose() throws IOException { file = null; } public void seek(long pos) throws IOException { super.seek(pos); pointer = (int) pos; } public long length() { return file.length; } public void flushToIndexOutput(IndexOutput indexOutput) throws IOException { super.flush(); if (file.buffers.size() == 0) { return; } if (file.buffers.size() == 1) { indexOutput.writeBytes((byte[]) file.buffers.get(0), (int) file.length); return; } int tempSize = file.buffers.size() - 1; int i; for (i = 0; i < tempSize; i++) { indexOutput.writeBytes((byte[]) file.buffers.get(i), bufferSize); } int leftOver = (int) (file.length % bufferSize); if (leftOver == 0) { indexOutput.writeBytes((byte[]) file.buffers.get(i), bufferSize); } else { indexOutput.writeBytes((byte[]) file.buffers.get(i), leftOver); } } }