001: package org.apache.lucene.store;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021:
022: /**
023: * A memory-resident {@link IndexOutput} implementation.
024: *
025: * @version $Id: RAMOutputStream.java 598693 2007-11-27 17:01:21Z mikemccand $
026: */
027:
028: public class RAMOutputStream extends IndexOutput {
029: static final int BUFFER_SIZE = 1024;
030:
031: private RAMFile file;
032:
033: private byte[] currentBuffer;
034: private int currentBufferIndex;
035:
036: private int bufferPosition;
037: private long bufferStart;
038: private int bufferLength;
039:
040: /** Construct an empty output buffer. */
041: public RAMOutputStream() {
042: this (new RAMFile());
043: }
044:
045: RAMOutputStream(RAMFile f) {
046: file = f;
047:
048: // make sure that we switch to the
049: // first needed buffer lazily
050: currentBufferIndex = -1;
051: currentBuffer = null;
052: }
053:
054: /** Copy the current contents of this buffer to the named output. */
055: public void writeTo(IndexOutput out) throws IOException {
056: flush();
057: final long end = file.length;
058: long pos = 0;
059: int buffer = 0;
060: while (pos < end) {
061: int length = BUFFER_SIZE;
062: long nextPos = pos + length;
063: if (nextPos > end) { // at the last buffer
064: length = (int) (end - pos);
065: }
066: out.writeBytes((byte[]) file.getBuffer(buffer++), length);
067: pos = nextPos;
068: }
069: }
070:
071: /** Resets this to an empty buffer. */
072: public void reset() {
073: try {
074: seek(0);
075: } catch (IOException e) { // should never happen
076: throw new RuntimeException(e.toString());
077: }
078:
079: file.setLength(0);
080: }
081:
082: public void close() throws IOException {
083: flush();
084: }
085:
086: public void seek(long pos) throws IOException {
087: // set the file length in case we seek back
088: // and flush() has not been called yet
089: setFileLength();
090: if (pos < bufferStart || pos >= bufferStart + bufferLength) {
091: currentBufferIndex = (int) (pos / BUFFER_SIZE);
092: switchCurrentBuffer();
093: }
094:
095: bufferPosition = (int) (pos % BUFFER_SIZE);
096: }
097:
098: public long length() {
099: return file.length;
100: }
101:
102: public void writeByte(byte b) throws IOException {
103: if (bufferPosition == bufferLength) {
104: currentBufferIndex++;
105: switchCurrentBuffer();
106: }
107: currentBuffer[bufferPosition++] = b;
108: }
109:
110: public void writeBytes(byte[] b, int offset, int len)
111: throws IOException {
112: while (len > 0) {
113: if (bufferPosition == bufferLength) {
114: currentBufferIndex++;
115: switchCurrentBuffer();
116: }
117:
118: int remainInBuffer = currentBuffer.length - bufferPosition;
119: int bytesToCopy = len < remainInBuffer ? len
120: : remainInBuffer;
121: System.arraycopy(b, offset, currentBuffer, bufferPosition,
122: bytesToCopy);
123: offset += bytesToCopy;
124: len -= bytesToCopy;
125: bufferPosition += bytesToCopy;
126: }
127: }
128:
129: private final void switchCurrentBuffer() throws IOException {
130: if (currentBufferIndex == file.numBuffers()) {
131: currentBuffer = file.addBuffer(BUFFER_SIZE);
132: } else {
133: currentBuffer = (byte[]) file.getBuffer(currentBufferIndex);
134: }
135: bufferPosition = 0;
136: bufferStart = (long) BUFFER_SIZE * (long) currentBufferIndex;
137: bufferLength = currentBuffer.length;
138: }
139:
140: private void setFileLength() {
141: long pointer = bufferStart + bufferPosition;
142: if (pointer > file.length) {
143: file.setLength(pointer);
144: }
145: }
146:
147: public void flush() throws IOException {
148: file.setLastModified(System.currentTimeMillis());
149: setFileLength();
150: }
151:
152: public long getFilePointer() {
153: return currentBufferIndex < 0 ? 0 : bufferStart
154: + bufferPosition;
155: }
156: }
|