diff --git a/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java b/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java index 00d79fa8934a..64d47913e2dd 100644 --- a/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java +++ b/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java @@ -947,7 +947,7 @@ private Status.SegmentInfoStatus testSegment( final Version version = info.info.getVersion(); if (info.info.maxDoc() <= 0) { - throw new CheckIndexException(" illegal number of documents: maxDoc=" + info.info.maxDoc()); + throw new CheckIndexException("illegal number of documents: maxDoc=" + info.info.maxDoc()); } int toLoseDocCount = info.info.maxDoc(); diff --git a/lucene/core/src/java/org/apache/lucene/index/CorruptSegmentInfoException.java b/lucene/core/src/java/org/apache/lucene/index/CorruptSegmentInfoException.java new file mode 100644 index 000000000000..6df76f9c2dfa --- /dev/null +++ b/lucene/core/src/java/org/apache/lucene/index/CorruptSegmentInfoException.java @@ -0,0 +1,70 @@ +/* + * 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; + +import org.apache.lucene.store.DataInput; +import org.apache.lucene.store.DataOutput; + +/** + * This exception is thrown when Lucene is unable to read a SegmentInfo file _N.si (When it is + * missing or corrupt) + */ +public class CorruptSegmentInfoException extends CorruptIndexException { + + // The segment name of the missing .si file is always stored for accurate error reporting + String segmentName; + + /** Create exception with the segmentName and message only */ + public CorruptSegmentInfoException(String segmentName, String message, DataInput input) { + super(message, input); + this.segmentName = segmentName; + } + + /** Create exception with the segmentName and message only */ + public CorruptSegmentInfoException(String segmentName, String message, DataOutput output) { + super(message, output); + this.segmentName = segmentName; + } + + /** Create exception with the segmentName, message and root cause. */ + public CorruptSegmentInfoException( + String segmentName, String message, DataInput input, Throwable cause) { + super(message, input, cause); + this.segmentName = segmentName; + } + + /** Create exception with the segmentName, message and root cause. */ + public CorruptSegmentInfoException( + String segmentName, String message, DataOutput output, Throwable cause) { + super(message, output, cause); + this.segmentName = segmentName; + } + + /** Create exception with the segmentName and message only */ + public CorruptSegmentInfoException( + String segmentName, String message, String resourceDescription) { + super(message, resourceDescription); + this.segmentName = segmentName; + } + + /** Create exception with the segmentName, message and root cause. */ + public CorruptSegmentInfoException( + String segmentName, String message, String resourceDescription, Throwable cause) { + super(message, resourceDescription, cause); + this.segmentName = segmentName; + } +} diff --git a/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java b/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java index 7caf2dbda8c4..67446cef2ceb 100644 --- a/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java +++ b/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java @@ -43,10 +43,7 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.store.IOContext; import org.apache.lucene.store.IndexOutput; -import org.apache.lucene.util.CollectionUtil; -import org.apache.lucene.util.IOUtils; -import org.apache.lucene.util.StringHelper; -import org.apache.lucene.util.Version; +import org.apache.lucene.util.*; /** * A collection of segmentInfo objects with methods for operating on those segments in relation to @@ -389,13 +386,25 @@ private static void parseSegmentInfos( } long totalDocs = 0; + SegmentInfo info; for (int seg = 0; seg < numSegments; seg++) { String segName = input.readString(); byte[] segmentID = new byte[StringHelper.ID_LENGTH]; input.readBytes(segmentID, 0, segmentID.length); Codec codec = readCodec(input); - SegmentInfo info = - codec.segmentInfoFormat().read(directory, segName, segmentID, IOContext.READ); + try { + info = codec.segmentInfoFormat().read(directory, segName, segmentID, IOContext.READ); + } catch (ThreadInterruptedException e) { + throw e; + } catch (Exception e) { + if (infoStream != null) { + message(e.getMessage()); + } + throw new CorruptSegmentInfoException( + segName, + "segment info file: " + segName + ".si cannot be read - it may be missing or corrupt", + input); + } info.setCodec(codec); totalDocs += info.maxDoc(); long delGen = CodecUtil.readBELong(input); diff --git a/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java b/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java index 5fde3977e7c0..2d0cb365d20f 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java @@ -217,7 +217,10 @@ public void doWork() throws Throwable { } catch (Exception e) { // can be rethrown as RuntimeException if it happens during a close listener if (!e.getMessage().contains("on purpose")) { - throw e; + // Caught "on-purpose" IOException can be rethrown as CorruptSegmentInfoException + if (!(e instanceof CorruptSegmentInfoException)) { + throw e; + } } // release resources IOUtils.closeWhileHandlingException(r1, r2);