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: /** Base implementation class for buffered {@link IndexOutput}. */
023: public abstract class BufferedIndexOutput extends IndexOutput {
024: static final int BUFFER_SIZE = 16384;
025:
026: private final byte[] buffer = new byte[BUFFER_SIZE];
027: private long bufferStart = 0; // position in file of buffer
028: private int bufferPosition = 0; // position in buffer
029:
030: /** Writes a single byte.
031: * @see IndexInput#readByte()
032: */
033: public void writeByte(byte b) throws IOException {
034: if (bufferPosition >= BUFFER_SIZE)
035: flush();
036: buffer[bufferPosition++] = b;
037: }
038:
039: /** Writes an array of bytes.
040: * @param b the bytes to write
041: * @param length the number of bytes to write
042: * @see IndexInput#readBytes(byte[],int,int)
043: */
044: public void writeBytes(byte[] b, int offset, int length)
045: throws IOException {
046: int bytesLeft = BUFFER_SIZE - bufferPosition;
047: // is there enough space in the buffer?
048: if (bytesLeft >= length) {
049: // we add the data to the end of the buffer
050: System.arraycopy(b, offset, buffer, bufferPosition, length);
051: bufferPosition += length;
052: // if the buffer is full, flush it
053: if (BUFFER_SIZE - bufferPosition == 0)
054: flush();
055: } else {
056: // is data larger then buffer?
057: if (length > BUFFER_SIZE) {
058: // we flush the buffer
059: if (bufferPosition > 0)
060: flush();
061: // and write data at once
062: flushBuffer(b, offset, length);
063: bufferStart += length;
064: } else {
065: // we fill/flush the buffer (until the input is written)
066: int pos = 0; // position in the input data
067: int pieceLength;
068: while (pos < length) {
069: pieceLength = (length - pos < bytesLeft) ? length
070: - pos : bytesLeft;
071: System.arraycopy(b, pos + offset, buffer,
072: bufferPosition, pieceLength);
073: pos += pieceLength;
074: bufferPosition += pieceLength;
075: // if the buffer is full, flush it
076: bytesLeft = BUFFER_SIZE - bufferPosition;
077: if (bytesLeft == 0) {
078: flush();
079: bytesLeft = BUFFER_SIZE;
080: }
081: }
082: }
083: }
084: }
085:
086: /** Forces any buffered output to be written. */
087: public void flush() throws IOException {
088: flushBuffer(buffer, bufferPosition);
089: bufferStart += bufferPosition;
090: bufferPosition = 0;
091: }
092:
093: /** Expert: implements buffer write. Writes bytes at the current position in
094: * the output.
095: * @param b the bytes to write
096: * @param len the number of bytes to write
097: */
098: private void flushBuffer(byte[] b, int len) throws IOException {
099: flushBuffer(b, 0, len);
100: }
101:
102: /** Expert: implements buffer write. Writes bytes at the current position in
103: * the output.
104: * @param b the bytes to write
105: * @param offset the offset in the byte array
106: * @param len the number of bytes to write
107: */
108: protected abstract void flushBuffer(byte[] b, int offset, int len)
109: throws IOException;
110:
111: /** Closes this stream to further operations. */
112: public void close() throws IOException {
113: flush();
114: }
115:
116: /** Returns the current position in this file, where the next write will
117: * occur.
118: * @see #seek(long)
119: */
120: public long getFilePointer() {
121: return bufferStart + bufferPosition;
122: }
123:
124: /** Sets current position in this file, where the next write will occur.
125: * @see #getFilePointer()
126: */
127: public void seek(long pos) throws IOException {
128: flush();
129: bufferStart = pos;
130: }
131:
132: /** The number of bytes in the file. */
133: public abstract long length() throws IOException;
134:
135: }
|