Index: src/test/org/apache/lucene/index/TestCheckIndex.java =================================================================== --- src/test/org/apache/lucene/index/TestCheckIndex.java (revision 692803) +++ src/test/org/apache/lucene/index/TestCheckIndex.java (working copy) @@ -49,13 +49,14 @@ ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); CheckIndex.out = new PrintStream(bos); - if (!CheckIndex.check(dir, false, null)) { + CheckIndexStatus indexStatus = CheckIndex.check(dir, false, null); + if (indexStatus.clean == false) { System.out.println("CheckIndex failed"); System.out.println(bos.toString()); fail(); } final List onlySegments = new ArrayList(); onlySegments.add("_0"); - assertTrue(CheckIndex.check(dir, false, onlySegments)); + assertTrue(CheckIndex.check(dir, false, onlySegments).clean == true); } } Index: src/test/org/apache/lucene/util/_TestUtil.java =================================================================== --- src/test/org/apache/lucene/util/_TestUtil.java (revision 692803) +++ src/test/org/apache/lucene/util/_TestUtil.java (working copy) @@ -23,6 +23,7 @@ import org.apache.lucene.index.MergeScheduler; import org.apache.lucene.index.ConcurrentMergeScheduler; import org.apache.lucene.index.CheckIndex; +import org.apache.lucene.index.CheckIndexStatus; import org.apache.lucene.store.Directory; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -60,7 +61,10 @@ public static boolean checkIndex(Directory dir) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); CheckIndex.out = new PrintStream(bos); - if (!CheckIndex.check(dir, false, null)) { + + //TODO: fix this + CheckIndexStatus indexStatus = CheckIndex.check(dir, false, null); + if (indexStatus == null || indexStatus.clean == false) { System.out.println("CheckIndex failed"); System.out.println(bos.toString()); throw new RuntimeException("CheckIndex failed"); Index: src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- src/java/org/apache/lucene/index/CheckIndex.java (revision 692803) +++ src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -42,7 +42,7 @@ public class CheckIndex { - public static PrintStream out = System.out; + public static PrintStream out = null; private static class MySegmentTermDocs extends SegmentTermDocs { @@ -63,21 +63,23 @@ } /** Returns true if index is clean, else false.*/ - public static boolean check(Directory dir, boolean doFix) throws IOException { + public static CheckIndexStatus check(Directory dir, boolean doFix) throws IOException { return check(dir, doFix, null); } /** Returns true if index is clean, else false.*/ - public static boolean check(Directory dir, boolean doFix, List onlySegments) throws IOException { + public static CheckIndexStatus check(Directory dir, boolean doFix, List onlySegments) throws IOException { NumberFormat nf = NumberFormat.getInstance(); SegmentInfos sis = new SegmentInfos(); - + CheckIndexStatus result = new CheckIndexStatus(); + result.dir = dir; try { sis.read(dir); } catch (Throwable t) { - out.println("ERROR: could not read any segments file in directory"); + msg("ERROR: could not read any segments file in directory"); + result.missingSegments = true; t.printStackTrace(out); - return false; + return result; } final int numSegments = sis.size(); @@ -86,17 +88,19 @@ try { input = dir.openInput(segmentsFileName); } catch (Throwable t) { - out.println("ERROR: could not open segments file in directory"); + msg("ERROR: could not open segments file in directory"); t.printStackTrace(out); - return false; + result.cantOpenSegments = true; + return result; } int format = 0; try { format = input.readInt(); } catch (Throwable t) { - out.println("ERROR: could not read segment file version in directory"); + msg("ERROR: could not read segment file version in directory"); t.printStackTrace(out); - return false; + result.missingSegmentVersion = true; + return result; } finally { if (input != null) input.close(); @@ -128,7 +132,10 @@ } } - out.println("Segments file=" + segmentsFileName + " numSegments=" + numSegments + " version=" + sFormat); + msg("Segments file=" + segmentsFileName + " numSegments=" + numSegments + " version=" + sFormat); + result.segmentsFileName = segmentsFileName; + result.numSegments = numSegments; + result.segmentFormat = sFormat; if (onlySegments != null) { out.print("\nChecking only these segments:"); @@ -136,56 +143,80 @@ while (it.hasNext()) { out.print(" " + it.next()); } - out.println(":"); + result.segmentsChecked.addAll(onlySegments); + msg(":"); } if (skip) { - out.println("\nERROR: this index appears to be created by a newer version of Lucene than this tool was compiled on; please re-compile this tool on the matching version of Lucene; exiting"); - return false; + msg("\nERROR: this index appears to be created by a newer version of Lucene than this tool was compiled on; please re-compile this tool on the matching version of Lucene; exiting"); + result.toolOutOfDate = true; + return result; } - SegmentInfos newSIS = (SegmentInfos) sis.clone(); - newSIS.clear(); - boolean changed = false; - int totLoseDocCount = 0; - int numBadSegments = 0; + + result.newSegments = (SegmentInfos) sis.clone(); + result.newSegments.clear(); + for(int i=0;iWARNING: this writes a new + * segments file into the index, effectively removing + * all documents in broken segments from the index. BE + * CAREFUL. */ + static public void fix(CheckIndexStatus result) throws IOException { + result.newSegments.commit(result.dir); + } static boolean assertsOn; @@ -357,6 +362,12 @@ return true; } + private static void msg(String msg) { + if (out != null) { + out.println(msg); + } + } + public static void main(String[] args) throws Throwable { boolean doFix = false; @@ -369,14 +380,14 @@ i++; } else if (args[i].equals("-segment")) { if (i == args.length-1) { - out.println("ERROR: missing name for -segment option"); + msg("ERROR: missing name for -segment option"); System.exit(1); } onlySegments.add(args[i+1]); i += 2; } else { if (indexPath != null) { - out.println("ERROR: unexpected extra argument '" + args[i] + "'"); + msg("ERROR: unexpected extra argument '" + args[i] + "'"); System.exit(1); } indexPath = args[i]; @@ -385,8 +396,8 @@ } if (indexPath == null) { - out.println("\nERROR: index path not specified"); - out.println("\nUsage: java org.apache.lucene.index.CheckIndex pathToIndex [-fix] [-segment X] [-segment Y]\n" + + msg("\nERROR: index path not specified"); + msg("\nUsage: java org.apache.lucene.index.CheckIndex pathToIndex [-fix] [-segment X] [-segment Y]\n" + "\n" + " -fix: actually write a new segments_N file, removing any problematic segments\n" + " -segment X: only check the specified segments. This can be specified multiple\n" + @@ -412,31 +423,55 @@ if (onlySegments.size() == 0) onlySegments = null; else if (doFix) { - out.println("ERROR: cannot specify both -fix and -segment"); + msg("ERROR: cannot specify both -fix and -segment"); System.exit(1); } assert testAsserts(); if (!assertsOn) - out.println("\nNOTE: testing will be more thorough if you run java with '-ea:org.apache.lucene', so assertions are enabled"); + msg("\nNOTE: testing will be more thorough if you run java with '-ea:org.apache.lucene', so assertions are enabled"); - out.println("\nOpening index @ " + indexPath + "\n"); + msg("\nOpening index @ " + indexPath + "\n"); Directory dir = null; try { dir = FSDirectory.getDirectory(indexPath); } catch (Throwable t) { - out.println("ERROR: could not open directory \"" + indexPath + "\"; exiting"); + msg("ERROR: could not open directory \"" + indexPath + "\"; exiting"); t.printStackTrace(out); System.exit(1); } - boolean isClean = check(dir, doFix, onlySegments); + CheckIndexStatus result = check(dir, doFix, onlySegments); + if (!result.clean) { + if (!doFix){ + msg("WARNING: would write new segments file, and " + result.totLoseDocCount + " documents would be lost, if -fix were specified\n"); + } else { + msg("WARNING: " + result.totLoseDocCount + " documents will be lost\n"); + msg("NOTE: will write new segments file in 5 seconds; this will remove " + result.totLoseDocCount + " docs from the index. THIS IS YOUR LAST CHANCE TO CTRL+C!"); + for(int s=0;s<5;s++) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + s--; + continue; + } + msg(" " + (5-i) + "..."); + } + msg("Writing..."); + CheckIndex.fix(result); + } + msg("OK"); + msg("Wrote new segments file \"" + result.newSegments.getCurrentSegmentFileName() + "\""); + } + msg(""); + final int exitCode; - if (isClean) + if (result != null && result.clean == true) exitCode = 0; else exitCode = 1; System.exit(exitCode); - } + } }