+++ /dev/null
-package org.apache.lucene.index;
-
-/**
- * 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.
- */
-
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.IndexInput;
-import org.apache.lucene.store.BufferedIndexInput;
-import org.apache.lucene.store.IndexOutput;
-import org.apache.lucene.store.Lock;
-
-import java.util.HashMap;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-/**
- * Class for accessing a compound stream.
- * This class implements a directory, but is limited to only read operations.
- * Directory methods that would normally modify data throw an exception.
- */
-class CompoundFileReader extends Directory {
-
- private int readBufferSize;
-
- private static final class FileEntry {
- long offset;
- long length;
- }
-
- // Base info
- private Directory directory;
- private String fileName;
-
- private IndexInput stream;
- private HashMap<String,FileEntry> entries = new HashMap<String,FileEntry>();
-
- public CompoundFileReader(Directory dir, String name) throws IOException {
- this(dir, name, BufferedIndexInput.BUFFER_SIZE);
- }
-
- public CompoundFileReader(Directory dir, String name, int readBufferSize) throws IOException {
- assert !(dir instanceof CompoundFileReader) : "compound file inside of compound file: " + name;
- directory = dir;
- fileName = name;
- this.readBufferSize = readBufferSize;
-
- boolean success = false;
-
- try {
- stream = dir.openInput(name, readBufferSize);
-
- // read the first VInt. If it is negative, it's the version number
- // otherwise it's the count (pre-3.1 indexes)
- int firstInt = stream.readVInt();
-
- final int count;
- final boolean stripSegmentName;
- if (firstInt < CompoundFileWriter.FORMAT_PRE_VERSION) {
- if (firstInt < CompoundFileWriter.FORMAT_CURRENT) {
- throw new CorruptIndexException("Incompatible format version: "
- + firstInt + " expected " + CompoundFileWriter.FORMAT_CURRENT);
- }
- // It's a post-3.1 index, read the count.
- count = stream.readVInt();
- stripSegmentName = false;
- } else {
- count = firstInt;
- stripSegmentName = true;
- }
-
- // read the directory and init files
- FileEntry entry = null;
- for (int i=0; i<count; i++) {
- long offset = stream.readLong();
- String id = stream.readString();
-
- if (stripSegmentName) {
- // Fix the id to not include the segment names. This is relevant for
- // pre-3.1 indexes.
- id = IndexFileNames.stripSegmentName(id);
- }
-
- if (entry != null) {
- // set length of the previous entry
- entry.length = offset - entry.offset;
- }
-
- entry = new FileEntry();
- entry.offset = offset;
- entries.put(id, entry);
- }
-
- // set the length of the final entry
- if (entry != null) {
- entry.length = stream.length() - entry.offset;
- }
-
- success = true;
-
- } finally {
- if (!success && (stream != null)) {
- try {
- stream.close();
- } catch (IOException e) { }
- }
- }
- }
-
- public Directory getDirectory() {
- return directory;
- }
-
- public String getName() {
- return fileName;
- }
-
- @Override
- public synchronized void close() throws IOException {
- if (stream == null)
- throw new IOException("Already closed");
-
- entries.clear();
- stream.close();
- stream = null;
- }
-
- @Override
- public synchronized IndexInput openInput(String id) throws IOException {
- // Default to readBufferSize passed in when we were opened
- return openInput(id, readBufferSize);
- }
-
- @Override
- public synchronized IndexInput openInput(String id, int readBufferSize) throws IOException {
- if (stream == null)
- throw new IOException("Stream closed");
-
- id = IndexFileNames.stripSegmentName(id);
- FileEntry entry = entries.get(id);
- if (entry == null) {
- throw new IOException("No sub-file with id " + id + " found (fileName=" + fileName + " files: " + entries.keySet() + ")");
- }
-
- return new CSIndexInput(stream, entry.offset, entry.length, readBufferSize);
- }
-
- /** Returns an array of strings, one for each file in the directory. */
- @Override
- public String[] listAll() {
- String[] res = entries.keySet().toArray(new String[entries.size()]);
- // Add the segment name
- String seg = fileName.substring(0, fileName.indexOf('.'));
- for (int i = 0; i < res.length; i++) {
- res[i] = seg + res[i];
- }
- return res;
- }
-
- /** Returns true iff a file with the given name exists. */
- @Override
- public boolean fileExists(String name) {
- return entries.containsKey(IndexFileNames.stripSegmentName(name));
- }
-
- /** Returns the time the compound file was last modified. */
- @Override
- public long fileModified(String name) throws IOException {
- return directory.fileModified(fileName);
- }
-
- /** Set the modified time of the compound file to now.
- * @deprecated Lucene never uses this API; it will be
- * removed in 4.0. */
- @Override
- @Deprecated
- public void touchFile(String name) throws IOException {
- directory.touchFile(fileName);
- }
-
- /** Not implemented
- * @throws UnsupportedOperationException */
- @Override
- public void deleteFile(String name) {
- throw new UnsupportedOperationException();
- }
-
- /** Not implemented
- * @throws UnsupportedOperationException */
- public void renameFile(String from, String to) {
- throw new UnsupportedOperationException();
- }
-
- /** Returns the length of a file in the directory.
- * @throws IOException if the file does not exist */
- @Override
- public long fileLength(String name) throws IOException {
- FileEntry e = entries.get(IndexFileNames.stripSegmentName(name));
- if (e == null)
- throw new FileNotFoundException(name);
- return e.length;
- }
-
- /** Not implemented
- * @throws UnsupportedOperationException */
- @Override
- public IndexOutput createOutput(String name) {
- throw new UnsupportedOperationException();
- }
-
- /** Not implemented
- * @throws UnsupportedOperationException */
- @Override
- public Lock makeLock(String name) {
- throw new UnsupportedOperationException();
- }
-
- /** Implementation of an IndexInput that reads from a portion of the
- * compound file. The visibility is left as "package" *only* because
- * this helps with testing since JUnit test cases in a different class
- * can then access package fields of this class.
- */
- static final class CSIndexInput extends BufferedIndexInput {
- IndexInput base;
- long fileOffset;
- long length;
-
- CSIndexInput(final IndexInput base, final long fileOffset, final long length) {
- this(base, fileOffset, length, BufferedIndexInput.BUFFER_SIZE);
- }
-
- CSIndexInput(final IndexInput base, final long fileOffset, final long length, int readBufferSize) {
- super(readBufferSize);
- this.base = (IndexInput)base.clone();
- this.fileOffset = fileOffset;
- this.length = length;
- }
-
- @Override
- public Object clone() {
- CSIndexInput clone = (CSIndexInput)super.clone();
- clone.base = (IndexInput)base.clone();
- clone.fileOffset = fileOffset;
- clone.length = length;
- return clone;
- }
-
- /** Expert: implements buffer refill. Reads bytes from the current
- * position in the input.
- * @param b the array to read bytes into
- * @param offset the offset in the array to start storing bytes
- * @param len the number of bytes to read
- */
- @Override
- protected void readInternal(byte[] b, int offset, int len) throws IOException {
- long start = getFilePointer();
- if(start + len > length)
- throw new IOException("read past EOF");
- base.seek(fileOffset + start);
- base.readBytes(b, offset, len, false);
- }
-
- /** Expert: implements seek. Sets current position in this file, where
- * the next {@link #readInternal(byte[],int,int)} will occur.
- * @see #readInternal(byte[],int,int)
- */
- @Override
- protected void seekInternal(long pos) {}
-
- /** Closes the stream to further operations. */
- @Override
- public void close() throws IOException {
- base.close();
- }
-
- @Override
- public long length() {
- return length;
- }
-
- @Override
- public void copyBytes(IndexOutput out, long numBytes) throws IOException {
- // Copy first whatever is in the buffer
- numBytes -= flushBuffer(out, numBytes);
-
- // If there are more bytes left to copy, delegate the copy task to the
- // base IndexInput, in case it can do an optimized copy.
- if (numBytes > 0) {
- long start = getFilePointer();
- if (start + numBytes > length) {
- throw new IOException("read past EOF");
- }
- base.seek(fileOffset + start);
- base.copyBytes(out, numBytes);
- }
- }
- }
-}