Index: contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsDictReader.java =================================================================== --- contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsDictReader.java (revision 965576) +++ contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsDictReader.java (working copy) @@ -42,7 +42,8 @@ @Override protected void readHeader(IndexInput in) throws IOException { - CodecUtil.checkHeader(in, AppendingTermsDictWriter.CODEC_NAME, StandardTermsDictWriter.VERSION_CURRENT); + CodecUtil.checkHeader(in, AppendingTermsDictWriter.CODEC_NAME, + StandardTermsDictWriter.VERSION_START, StandardTermsDictWriter.VERSION_CURRENT); } @Override Index: contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsIndexReader.java =================================================================== --- contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsIndexReader.java (revision 965576) +++ contrib/misc/src/java/org/apache/lucene/index/codecs/appending/AppendingTermsIndexReader.java (working copy) @@ -37,7 +37,8 @@ @Override protected void readHeader(IndexInput input) throws IOException { - CodecUtil.checkHeader(input, AppendingTermsIndexWriter.CODEC_NAME, AppendingTermsIndexWriter.VERSION_START); + CodecUtil.checkHeader(input, AppendingTermsIndexWriter.CODEC_NAME, + AppendingTermsIndexWriter.VERSION_START, AppendingTermsIndexWriter.VERSION_START); } @Override Index: src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- src/java/org/apache/lucene/index/CheckIndex.java (revision 965576) +++ src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -24,6 +24,7 @@ import org.apache.lucene.document.AbstractField; // for javadocs import org.apache.lucene.document.Document; import org.apache.lucene.index.codecs.CodecProvider; +import org.apache.lucene.index.codecs.DefaultSegmentInfosWriter; import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; @@ -343,13 +344,16 @@ String sFormat = ""; boolean skip = false; - if (format == SegmentInfos.FORMAT_DIAGNOSTICS) + if (format == DefaultSegmentInfosWriter.FORMAT_DIAGNOSTICS) { sFormat = "FORMAT_DIAGNOSTICS [Lucene 2.9]"; - else if (format == SegmentInfos.FORMAT_4_0) - sFormat = "FORMAT_FLEX_POSTINGS [Lucene 4.0]"; - else if (format < SegmentInfos.CURRENT_FORMAT) { - sFormat = "int=" + format + " [newer version of Lucene than this tool]"; + } else if (format == DefaultSegmentInfosWriter.FORMAT_4_0) { + sFormat = "FORMAT_4_0 [Lucene 4.0]"; + } else if (format < DefaultSegmentInfosWriter.FORMAT_CURRENT) { + sFormat = "int=" + format + " [newer version of Lucene than this tool supports]"; skip = true; + } else if (format > DefaultSegmentInfosWriter.FORMAT_MINIMUM) { + sFormat = "int=" + format + " [older version of Lucene than this tool supports]"; + skip = true; } result.segmentsFileName = segmentsFileName; Index: src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosReader.java =================================================================== --- src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosReader.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosReader.java (working copy) @@ -20,6 +20,8 @@ import java.io.IOException; import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.IndexFormatTooOldException; +import org.apache.lucene.index.IndexFormatTooNewException; import org.apache.lucene.index.SegmentInfo; import org.apache.lucene.index.SegmentInfos; import org.apache.lucene.store.ChecksumIndexInput; @@ -41,8 +43,10 @@ int format = input.readInt(); // check that it is a format we can understand - if (format < SegmentInfos.CURRENT_FORMAT) - throw new CorruptIndexException("Unknown (newer than us?) format version: " + format); + if (format > DefaultSegmentInfosWriter.FORMAT_MINIMUM) + throw new IndexFormatTooOldException("Unsupported format version: " + format); + if (format < DefaultSegmentInfosWriter.FORMAT_CURRENT) + throw new IndexFormatTooNewException("Unsupported format version: " + format); infos.version = input.readLong(); // read version infos.counter = input.readInt(); // read counter Index: src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java =================================================================== --- src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java (working copy) @@ -31,11 +31,26 @@ */ public class DefaultSegmentInfosWriter extends SegmentInfosWriter { + /** This format adds optional per-segment String + * diagnostics storage, and switches userData to Map */ + public static final int FORMAT_DIAGNOSTICS = -9; + + /** Each segment records whether its postings are written + * in the new flex format */ + public static final int FORMAT_4_0 = -10; + + /** This must always point to the most recent file format. + * whenever you add a new format, make it 1 smaller (negative version logic)! */ + public static final int FORMAT_CURRENT = FORMAT_4_0; + + /** This must always point to the first supported file format. */ + public static final int FORMAT_MINIMUM = FORMAT_DIAGNOSTICS; + @Override public IndexOutput writeInfos(Directory dir, String segmentFileName, SegmentInfos infos) throws IOException { IndexOutput out = createOutput(dir, segmentFileName); - out.writeInt(SegmentInfos.CURRENT_FORMAT); // write FORMAT + out.writeInt(FORMAT_CURRENT); // write FORMAT out.writeLong(++infos.version); // every write changes // the index out.writeInt(infos.counter); // write counter Index: src/java/org/apache/lucene/index/codecs/intblock/SimpleIntBlockIndexInput.java =================================================================== --- src/java/org/apache/lucene/index/codecs/intblock/SimpleIntBlockIndexInput.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/intblock/SimpleIntBlockIndexInput.java (working copy) @@ -37,7 +37,8 @@ public SimpleIntBlockIndexInput(Directory dir, String fileName, int readBufferSize) throws IOException { IndexInput in = dir.openInput(fileName, readBufferSize); - CodecUtil.checkHeader(in, SimpleIntBlockIndexOutput.CODEC, SimpleIntBlockIndexOutput.VERSION_START); + CodecUtil.checkHeader(in, SimpleIntBlockIndexOutput.CODEC, + SimpleIntBlockIndexOutput.VERSION_START, SimpleIntBlockIndexOutput.VERSION_START); init(in); } Index: src/java/org/apache/lucene/index/codecs/preflex/SegmentTermEnum.java =================================================================== --- src/java/org/apache/lucene/index/codecs/preflex/SegmentTermEnum.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/preflex/SegmentTermEnum.java (working copy) @@ -22,6 +22,8 @@ import org.apache.lucene.index.FieldInfos; import org.apache.lucene.index.Term; import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.IndexFormatTooOldException; +import org.apache.lucene.index.IndexFormatTooNewException; /** * @deprecated No longer used with flex indexing, except for @@ -40,7 +42,11 @@ public static final int FORMAT_VERSION_UTF8_LENGTH_IN_BYTES = -4; // NOTE: always change this if you switch to a new format! + // whenever you add a new format, make it 1 smaller (negative version logic)! public static final int FORMAT_CURRENT = FORMAT_VERSION_UTF8_LENGTH_IN_BYTES; + + // when removing support for old versions, levae the last supported version here + public static final int FORMAT_MINIMUM = FORMAT_VERSION_UTF8_LENGTH_IN_BYTES; private TermBuffer termBuffer = new TermBuffer(); private TermBuffer prevBuffer = new TermBuffer(); @@ -78,8 +84,10 @@ format = firstInt; // check that it is a format we can understand - if (format < FORMAT_CURRENT) - throw new CorruptIndexException("Unknown format version:" + format + " expected " + FORMAT_CURRENT + " or higher"); + if (format > FORMAT_MINIMUM) + throw new IndexFormatTooOldException("Unsupported format version: " + format); + if (format < FORMAT_CURRENT) + throw new IndexFormatTooNewException("Unsupported format version: " + format); size = input.readLong(); // read the size Index: src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsReaderImpl.java =================================================================== --- src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsReaderImpl.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsReaderImpl.java (working copy) @@ -51,7 +51,8 @@ @Override public void init(IndexInput termsIn) throws IOException { - CodecUtil.checkHeader(termsIn, PulsingPostingsWriterImpl.CODEC, PulsingPostingsWriterImpl.VERSION_START); + CodecUtil.checkHeader(termsIn, PulsingPostingsWriterImpl.CODEC, + PulsingPostingsWriterImpl.VERSION_START, PulsingPostingsWriterImpl.VERSION_START); maxPulsingDocFreq = termsIn.readVInt(); wrappedPostingsReader.init(termsIn); } Index: src/java/org/apache/lucene/index/codecs/sep/SepPostingsReaderImpl.java =================================================================== --- src/java/org/apache/lucene/index/codecs/sep/SepPostingsReaderImpl.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/sep/SepPostingsReaderImpl.java (working copy) @@ -95,7 +95,8 @@ @Override public void init(IndexInput termsIn) throws IOException { // Make sure we are talking to the matching past writer - CodecUtil.checkHeader(termsIn, SepPostingsWriterImpl.CODEC, SepPostingsWriterImpl.VERSION_START); + CodecUtil.checkHeader(termsIn, SepPostingsWriterImpl.CODEC, + SepPostingsWriterImpl.VERSION_START, SepPostingsWriterImpl.VERSION_START); skipInterval = termsIn.readInt(); maxSkipLevels = termsIn.readInt(); } Index: src/java/org/apache/lucene/index/codecs/sep/SingleIntIndexInput.java =================================================================== --- src/java/org/apache/lucene/index/codecs/sep/SingleIntIndexInput.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/sep/SingleIntIndexInput.java (working copy) @@ -36,7 +36,8 @@ public SingleIntIndexInput(Directory dir, String fileName, int readBufferSize) throws IOException { in = dir.openInput(fileName, readBufferSize); - CodecUtil.checkHeader(in, SingleIntIndexOutput.CODEC, SingleIntIndexOutput.VERSION_START); + CodecUtil.checkHeader(in, SingleIntIndexOutput.CODEC, + SingleIntIndexOutput.VERSION_START, SingleIntIndexOutput.VERSION_START); } @Override Index: src/java/org/apache/lucene/index/codecs/standard/SimpleStandardTermsIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/codecs/standard/SimpleStandardTermsIndexReader.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/standard/SimpleStandardTermsIndexReader.java (working copy) @@ -146,7 +146,8 @@ } protected void readHeader(IndexInput input) throws IOException { - CodecUtil.checkHeader(input, SimpleStandardTermsIndexWriter.CODEC_NAME, SimpleStandardTermsIndexWriter.VERSION_START); + CodecUtil.checkHeader(input, SimpleStandardTermsIndexWriter.CODEC_NAME, + SimpleStandardTermsIndexWriter.VERSION_START, SimpleStandardTermsIndexWriter.VERSION_START); dirOffset = input.readLong(); } Index: src/java/org/apache/lucene/index/codecs/standard/StandardPostingsReaderImpl.java =================================================================== --- src/java/org/apache/lucene/index/codecs/standard/StandardPostingsReaderImpl.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/standard/StandardPostingsReaderImpl.java (working copy) @@ -73,7 +73,8 @@ public void init(IndexInput termsIn) throws IOException { // Make sure we are talking to the matching past writer - CodecUtil.checkHeader(termsIn, StandardPostingsWriterImpl.CODEC, StandardPostingsWriterImpl.VERSION_START); + CodecUtil.checkHeader(termsIn, StandardPostingsWriterImpl.CODEC, + StandardPostingsWriterImpl.VERSION_START, StandardPostingsWriterImpl.VERSION_START); skipInterval = termsIn.readInt(); maxSkipLevels = termsIn.readInt(); Index: src/java/org/apache/lucene/index/codecs/standard/StandardTermsDictReader.java =================================================================== --- src/java/org/apache/lucene/index/codecs/standard/StandardTermsDictReader.java (revision 965576) +++ src/java/org/apache/lucene/index/codecs/standard/StandardTermsDictReader.java (working copy) @@ -153,7 +153,8 @@ } protected void readHeader(IndexInput input) throws IOException { - CodecUtil.checkHeader(in, StandardTermsDictWriter.CODEC_NAME, StandardTermsDictWriter.VERSION_CURRENT); + CodecUtil.checkHeader(in, StandardTermsDictWriter.CODEC_NAME, + StandardTermsDictWriter.VERSION_START, StandardTermsDictWriter.VERSION_CURRENT); dirOffset = in.readLong(); } Index: src/java/org/apache/lucene/index/FieldInfos.java =================================================================== --- src/java/org/apache/lucene/index/FieldInfos.java (revision 965576) +++ src/java/org/apache/lucene/index/FieldInfos.java (working copy) @@ -39,8 +39,11 @@ // First used in 2.9; prior to 2.9 there was no format header public static final int FORMAT_START = -2; - static final int CURRENT_FORMAT = FORMAT_START; + // whenever you add a new format, make it 1 smaller (negative version logic)! + static final int FORMAT_CURRENT = FORMAT_START; + static final int FORMAT_MINIMUM = FORMAT_START; + static final byte IS_INDEXED = 0x1; static final byte STORE_TERMVECTOR = 0x2; static final byte STORE_POSITIONS_WITH_TERMVECTOR = 0x4; @@ -286,7 +289,7 @@ } public void write(IndexOutput output) throws IOException { - output.writeVInt(CURRENT_FORMAT); + output.writeVInt(FORMAT_CURRENT); output.writeVInt(size()); for (int i = 0; i < size(); i++) { FieldInfo fi = fieldInfo(i); @@ -307,9 +310,12 @@ private void read(IndexInput input, String fileName) throws IOException { format = input.readVInt(); - if (format > FORMAT_START) { - throw new CorruptIndexException("unrecognized format " + format + " in file \"" + fileName + "\""); + if (format < FORMAT_CURRENT) { + throw new IndexFormatTooNewException("Unsupported format version: " + format); } + if (format > FORMAT_MINIMUM) { + throw new IndexFormatTooOldException("Unsupported format version: " + format); + } final int size = input.readVInt(); //read in the size Index: src/java/org/apache/lucene/index/FieldsReader.java =================================================================== --- src/java/org/apache/lucene/index/FieldsReader.java (revision 965576) +++ src/java/org/apache/lucene/index/FieldsReader.java (working copy) @@ -104,9 +104,10 @@ format = cloneableIndexStream.readInt(); + if (format < FieldsWriter.FORMAT_MINIMUM) + throw new IndexFormatTooOldException("Unsupported format version: " + format); if (format > FieldsWriter.FORMAT_CURRENT) - throw new CorruptIndexException("Incompatible format version: " + format + " expected " - + FieldsWriter.FORMAT_CURRENT + " or lower"); + throw new IndexFormatTooNewException("Unsupported format version: " + format); fieldsStream = (IndexInput) cloneableFieldsStream.clone(); @@ -185,11 +186,9 @@ } boolean canReadRawDocs() { - // Disable reading raw docs in 2.x format, because of the removal of compressed - // fields in 3.0. We don't want rawDocs() to decode field bits to figure out - // if a field was compressed, hence we enforce ordinary (non-raw) stored field merges - // for <3.0 indexes. - return format >= FieldsWriter.FORMAT_LUCENE_3_0_NO_COMPRESSED_FIELDS; + // Since we currently only support >3.0 format anymore, always return true! + // I leave this method in because it may help for later format changes. + return true; } final Document doc(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { @@ -306,7 +305,6 @@ private void addField(Document doc, FieldInfo fi, boolean binary, boolean tokenize) throws CorruptIndexException, IOException { - //we have a binary stored field, and it may be compressed if (binary) { int toRead = fieldsStream.readVInt(); final byte[] b = new byte[toRead]; Index: src/java/org/apache/lucene/index/FieldsWriter.java =================================================================== --- src/java/org/apache/lucene/index/FieldsWriter.java (revision 965576) +++ src/java/org/apache/lucene/index/FieldsWriter.java (working copy) @@ -39,6 +39,9 @@ // switch to a new format! static final int FORMAT_CURRENT = FORMAT_LUCENE_3_0_NO_COMPRESSED_FIELDS; + // when removing support for old versions, leave the last supported version here + static final int FORMAT_MINIMUM = FORMAT_LUCENE_3_0_NO_COMPRESSED_FIELDS; + private FieldInfos fieldInfos; private IndexOutput fieldsStream; Index: src/java/org/apache/lucene/index/IndexFormatTooNewException.java =================================================================== --- src/java/org/apache/lucene/index/IndexFormatTooNewException.java (revision 0) +++ src/java/org/apache/lucene/index/IndexFormatTooNewException.java (revision 0) @@ -0,0 +1,28 @@ +/** + * 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.index; + +/** + * This exception is thrown when Lucene detects + * an index that is newer than this Lucene version. + */ +public class IndexFormatTooNewException extends CorruptIndexException { + public IndexFormatTooNewException(String message) { + super(message); + } +} Property changes on: src\java\org\apache\lucene\index\IndexFormatTooNewException.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Index: src/java/org/apache/lucene/index/IndexFormatTooOldException.java =================================================================== --- src/java/org/apache/lucene/index/IndexFormatTooOldException.java (revision 0) +++ src/java/org/apache/lucene/index/IndexFormatTooOldException.java (revision 0) @@ -0,0 +1,28 @@ +/** + * 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.index; + +/** + * This exception is thrown when Lucene detects + * an index that is too old for this Lucene version + */ +public class IndexFormatTooOldException extends CorruptIndexException { + public IndexFormatTooOldException(String message) { + super(message + " (this version of Lucene only supports indexes created with Lucene 3.0 and later)"); + } +} Property changes on: src\java\org\apache\lucene\index\IndexFormatTooOldException.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Index: src/java/org/apache/lucene/index/SegmentInfo.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfo.java (revision 965576) +++ src/java/org/apache/lucene/index/SegmentInfo.java (working copy) @@ -22,6 +22,7 @@ import org.apache.lucene.store.IndexInput; import org.apache.lucene.index.codecs.Codec; import org.apache.lucene.index.codecs.CodecProvider; +import org.apache.lucene.index.codecs.DefaultSegmentInfosWriter; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -154,7 +155,7 @@ docStoreSegment = name; docStoreIsCompoundFile = false; } - if (format > SegmentInfos.FORMAT_4_0) { + if (format > DefaultSegmentInfosWriter.FORMAT_4_0) { // pre-4.0 indexes write a byte if there is a single norms file byte b = input.readByte(); assert 1 == b; @@ -177,7 +178,7 @@ // System.out.println(Thread.currentThread().getName() + ": si.read hasProx=" + hasProx + " seg=" + name); - if (format <= SegmentInfos.FORMAT_4_0) + if (format <= DefaultSegmentInfosWriter.FORMAT_4_0) codecName = input.readString(); else codecName = "PreFlex"; Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 965576) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -53,20 +53,10 @@ * be removed, however the numbers should continue to decrease. */ - /** Used for the segments.gen file only! */ + /** Used for the segments.gen file only! + * Whenever you add a new format, make it 1 smaller (negative version logic)! */ public static final int FORMAT_SEGMENTS_GEN_CURRENT = -2; - - /** This format adds optional per-segment String - * diagnostics storage, and switches userData to Map */ - public static final int FORMAT_DIAGNOSTICS = -9; - - /** Each segment records whether its postings are written - * in the new flex format */ - public static final int FORMAT_4_0 = -10; - - /* This must always point to the most recent file format. */ - public static final int CURRENT_FORMAT = FORMAT_4_0; - + public int counter = 0; // used to name new segments /** @@ -556,9 +546,16 @@ genB = gen0; break; } + } else { + /* TODO: Investigate this! + throw new IndexFormatTooNewException("segments.gen version number invalid: " + version + + " (must be " + FORMAT_SEGMENTS_GEN_CURRENT + ")"); + */ } } catch (IOException err2) { - // will retry + // rethrow any format exception + if (err2 instanceof CorruptIndexException) throw err2; + // else will retry } finally { genInput.close(); } Index: src/java/org/apache/lucene/index/TermVectorsReader.java =================================================================== --- src/java/org/apache/lucene/index/TermVectorsReader.java (revision 965576) +++ src/java/org/apache/lucene/index/TermVectorsReader.java (working copy) @@ -35,7 +35,11 @@ static final int FORMAT_UTF8_LENGTH_IN_BYTES = 4; // NOTE: always change this if you switch to a new format! + // whenever you add a new format, make it 1 larger (positive version logic)! static final int FORMAT_CURRENT = FORMAT_UTF8_LENGTH_IN_BYTES; + + // when removing support for old versions, leave the last supported version here + static final int FORMAT_MINIMUM = FORMAT_UTF8_LENGTH_IN_BYTES; //The size in bytes that the FORMAT_VERSION will take up at the beginning of each file static final int FORMAT_SIZE = 4; @@ -186,10 +190,10 @@ private int checkValidFormat(IndexInput in) throws CorruptIndexException, IOException { int format = in.readInt(); - if (format > FORMAT_CURRENT) { - throw new CorruptIndexException("Incompatible format version: " + format + " expected " - + FORMAT_CURRENT + " or less"); - } + if (format < FORMAT_MINIMUM) + throw new IndexFormatTooOldException("Unsupported format version: " + format); + if (format > FORMAT_CURRENT) + throw new IndexFormatTooNewException("Unsupported format version: " + format); return format; } Index: src/java/org/apache/lucene/util/CodecUtil.java =================================================================== --- src/java/org/apache/lucene/util/CodecUtil.java (revision 965576) +++ src/java/org/apache/lucene/util/CodecUtil.java (working copy) @@ -21,6 +21,8 @@ import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.IndexInput; import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.IndexFormatTooNewException; +import org.apache.lucene.index.IndexFormatTooOldException; import java.io.IOException; @@ -48,7 +50,7 @@ return 9+codec.length(); } - public static int checkHeader(IndexInput in, String codec, int maxVersion) + public static int checkHeader(IndexInput in, String codec, int minVersion, int maxVersion) throws IOException { // Safety to guard against reading a bogus string: @@ -63,8 +65,11 @@ } final int actualVersion = in.readInt(); + if (actualVersion < minVersion) { + throw new IndexFormatTooOldException("version " + actualVersion + " is too old (expected >= version " + minVersion + ")"); + } if (actualVersion > maxVersion) { - throw new CorruptIndexException("version " + actualVersion + " is too new (expected <= version " + maxVersion + ")"); + throw new IndexFormatTooNewException("version " + actualVersion + " is too new (expected <= version " + maxVersion + ")"); } return actualVersion; Index: src/java/org/apache/lucene/util/packed/PackedInts.java =================================================================== --- src/java/org/apache/lucene/util/packed/PackedInts.java (revision 965576) +++ src/java/org/apache/lucene/util/packed/PackedInts.java (working copy) @@ -157,7 +157,7 @@ * @lucene.internal */ public static Reader getReader(IndexInput in) throws IOException { - CodecUtil.checkHeader(in, CODEC_NAME, VERSION_START); + CodecUtil.checkHeader(in, CODEC_NAME, VERSION_START, VERSION_START); final int bitsPerValue = in.readVInt(); assert bitsPerValue > 0 && bitsPerValue <= 64: "bitsPerValue=" + bitsPerValue; final int valueCount = in.readVInt(); @@ -188,7 +188,7 @@ * @lucene.internal */ public static ReaderIterator getReaderIterator(IndexInput in) throws IOException { - CodecUtil.checkHeader(in, CODEC_NAME, VERSION_START); + CodecUtil.checkHeader(in, CODEC_NAME, VERSION_START, VERSION_START); final int bitsPerValue = in.readVInt(); assert bitsPerValue > 0 && bitsPerValue <= 64: "bitsPerValue=" + bitsPerValue; final int valueCount = in.readVInt(); Index: src/test/org/apache/lucene/index/TestBackwardsCompatibility.java =================================================================== --- src/test/org/apache/lucene/index/TestBackwardsCompatibility.java (revision 965576) +++ src/test/org/apache/lucene/index/TestBackwardsCompatibility.java (working copy) @@ -23,6 +23,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.util.Arrays; import java.util.Enumeration; import java.util.List; @@ -127,6 +129,74 @@ "31.nocfs", }; + final String[] unsupportedNames = {"19.cfs", + "19.nocfs", + "20.cfs", + "20.nocfs", + "21.cfs", + "21.nocfs", + "22.cfs", + "22.nocfs", + "23.cfs", + "23.nocfs", + "24.cfs", + "24.nocfs", + "29.cfs", + "29.nocfs", + }; + + /** This test checks that *only* IndexFormatTooOldExceptions are throws when you open and operate on too old indexes! */ + public void testUnsupportedOldIndexes() throws Exception { + for(int i=0;i3.0 stored field change + fail("IndexReader.open should not pass for "+unsupportedNames[i]); + } catch (IndexFormatTooOldException e) { + // pass + } finally { + if (reader != null) reader.close(); + reader = null; + } + + try { + writer = new IndexWriter(dir, new IndexWriterConfig( + TEST_VERSION_CURRENT, new MockAnalyzer()) + .setMergeScheduler(new SerialMergeScheduler()) // no threads! + ); + writer.optimize(); + reader = writer.getReader(); + reader.document(0); // to catch also 2.9->3.0 stored field change + fail("IndexWriter creation should not pass for "+unsupportedNames[i]); + } catch (IndexFormatTooOldException e) { + // pass + } finally { + if (reader != null) reader.close(); + reader = null; + if (writer != null) writer.close(); + writer = null; + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); + CheckIndex checker = new CheckIndex(dir); + checker.setInfoStream(new PrintStream(bos)); + CheckIndex.Status indexStatus = checker.checkIndex(); + assertFalse(indexStatus.clean); + assertTrue(bos.toString().contains(IndexFormatTooOldException.class.getName())); + + dir.close(); + rmDir(unsupportedNames[i]); + } + } + public void testOptimizeOldIndex() throws Exception { for(int i=0;i