blob: ebc5cfecafdcd09b6b92d291a229e95ca9d0ed46 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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;
import java.io.Closeable;
import java.io.IOException;
/**
* Abstract base class for input from a file in a {@link Directory}. A
* random-access input stream. Used for all Lucene index input operations.
*
* <p>{@code IndexInput} may only be used from one thread, because it is not
* thread safe (it keeps internal state like file position). To allow
* multithreaded use, every {@code IndexInput} instance must be cloned before
* it is used in another thread. Subclasses must therefore implement {@link #clone()},
* returning a new {@code IndexInput} which operates on the same underlying
* resource, but positioned independently.
*
* <p><b>Warning:</b> Lucene never closes cloned
* {@code IndexInput}s, it will only call {@link #close()} on the original object.
*
* <p>If you access the cloned IndexInput after closing the original object,
* any <code>readXXX</code> methods will throw {@link AlreadyClosedException}.
*
* @see Directory
*/
public abstract class IndexInput extends DataInput implements Cloneable,Closeable {
private final String resourceDescription;
/** resourceDescription should be a non-null, opaque string
* describing this resource; it's returned from
* {@link #toString}. */
protected IndexInput(String resourceDescription) {
if (resourceDescription == null) {
throw new IllegalArgumentException("resourceDescription must not be null");
}
this.resourceDescription = resourceDescription;
}
/** Closes the stream to further operations. */
@Override
public abstract void close() throws IOException;
/** Returns the current position in this file, where the next read will
* occur.
* @see #seek(long)
*/
public abstract long getFilePointer();
/** Sets current position in this file, where the next read will occur. If this is
* beyond the end of the file then this will throw {@code EOFException} and then the
* stream is in an undetermined state.
*
* @see #getFilePointer()
*/
public abstract void seek(long pos) throws IOException;
/** The number of bytes in the file. */
public abstract long length();
@Override
public String toString() {
return resourceDescription;
}
/** {@inheritDoc}
*
* <p><b>Warning:</b> Lucene never closes cloned
* {@code IndexInput}s, it will only call {@link #close()} on the original object.
*
* <p>If you access the cloned IndexInput after closing the original object,
* any <code>readXXX</code> methods will throw {@link AlreadyClosedException}.
*
* <p>This method is NOT thread safe, so if the current {@code IndexInput}
* is being used by one thread while {@code clone} is called by another,
* disaster could strike.
*/
@Override
public IndexInput clone() {
return (IndexInput) super.clone();
}
/**
* Creates a slice of this index input, with the given description, offset, and length.
* The slice is sought to the beginning.
*/
public abstract IndexInput slice(String sliceDescription, long offset, long length) throws IOException;
/** Subclasses call this to get the String for resourceDescription of a slice of this {@code IndexInput}. */
protected String getFullSliceDescription(String sliceDescription) {
if (sliceDescription == null) {
// Clones pass null sliceDescription:
return toString();
} else {
return toString() + " [slice=" + sliceDescription + "]";
}
}
/**
* Creates a random-access slice of this index input, with the given offset and length.
* <p>
* The default implementation calls {@link #slice}, and it doesn't support random access,
* it implements absolute reads as seek+read.
*/
public RandomAccessInput randomAccessSlice(long offset, long length) throws IOException {
final IndexInput slice = slice("randomaccess", offset, length);
if (slice instanceof RandomAccessInput) {
// slice() already supports random access
return (RandomAccessInput) slice;
} else {
// return default impl
return new RandomAccessInput() {
@Override
public byte readByte(long pos) throws IOException {
slice.seek(pos);
return slice.readByte();
}
@Override
public short readShort(long pos) throws IOException {
slice.seek(pos);
return slice.readShort();
}
@Override
public int readInt(long pos) throws IOException {
slice.seek(pos);
return slice.readInt();
}
@Override
public long readLong(long pos) throws IOException {
slice.seek(pos);
return slice.readLong();
}
@Override
public String toString() {
return "RandomAccessInput(" + IndexInput.this.toString() + ")";
}
};
}
}
}