Solr4.8.0源码分析(13)之LuceneCore的索引修复
2014-10-23 00:16 追风的蓝宝 阅读(1682) 评论(0) 编辑 收藏 举报Solr4.8.0源码分析(13)之LuceneCore的索引修复
题记:今天在公司研究elasticsearch,突然看到一篇博客说elasticsearch具有索引修复功能,顿感好奇,于是点进去看了下,发现原来是Lucene Core自带的功能。说实话之前学习Lucene文件格式的时候就想做一个索引文件解析和检测的工具,也动手写了一部分,最后没想到发现了一个已有的工具,正好对照着学习下。
索引的修复主要是用到CheckIndex.java这个类,可以直接查看类的Main函数来了解下。
1. CheckIndex的使用
首先使用以下命令来查看lucenecore.jar怎么使用:
1 192:lib rcf$ java -cp lucene-core-4.8-SNAPSHOT.jar -ea:org.apache.lucene... org.apache.lucene.index.CheckIndex 2 3 ERROR: index path not specified 4 5 Usage: java org.apache.lucene.index.CheckIndex pathToIndex [-fix] [-crossCheckTermVectors] [-segment X] [-segment Y] [-dir-impl X] 6 7 -fix: actually write a new segments_N file, removing any problematic segments 8 -crossCheckTermVectors: verifies that term vectors match postings; THIS IS VERY SLOW! 9 -codec X: when fixing, codec to write the new segments_N file with 10 -verbose: print additional details 11 -segment X: only check the specified segments. This can be specified multiple 12 times, to check more than one segment, eg '-segment _2 -segment _a'. 13 You can't use this with the -fix option 14 -dir-impl X: use a specific FSDirectory implementation. If no package is specified the org.apache.lucene.store package will be used. 15 16 **WARNING**: -fix should only be used on an emergency basis as it will cause 17 documents (perhaps many) to be permanently removed from the index. Always make 18 a backup copy of your index before running this! Do not run this tool on an index 19 that is actively being written to. You have been warned! 20 21 Run without -fix, this tool will open the index, report version information 22 and report any exceptions it hits and what action it would take if -fix were 23 specified. With -fix, this tool will remove any segments that have issues and 24 write a new segments_N file. This means all documents contained in the affected 25 segments will be removed. 26 27 This tool exits with exit code 1 if the index cannot be opened or has any 28 corruption, else 0.
当敲java -cp lucene-core-4.8-SNAPSHOT.jar -ea:org.apache.lucene... org.apache.lucene.index.CheckIndex 这个就能看到相当于help的信息啦,但是为什么这里用这么一串奇怪的命令呢?通过java -help来查看-cp 以及 -ea就可以发现,-cp其实等同于-classpath 提供类和jar的搜索路径,-ea等同于-enableassertions提供是否启动断言设置。所以上述的命令其实可以简化为java -cp lucene-core-4.8-SNAPSHOT.jar org.apache.lucene.index.CheckIndex 。
首先来检查下索引的情况:可以看出信息蛮清楚明了的。
1 userdeMacBook-Pro:lib rcf$ java -cp lucene-core-4.8-SNAPSHOT.jar -ea:org.apache.lucene.index... org.apache.lucene.index.CheckIndex ../../../../../../solr/Solr/test/data/index 2 3 Opening index @ ../../../../../../solr/Solr/test/data/index 4 5 Segments file=segments_r numSegments=7 version=4.8 format= userData={commitTimeMSec=1411221019854} 6 1 of 7: name=_k docCount=18001 7 codec=Lucene46 8 compound=false 9 numFiles=10 10 size (MB)=0.493 11 diagnostics = {timestamp=1411221019346, os=Mac OS X, os.version=10.9.4, mergeFactor=10, source=merge, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, mergeMaxNumSegments=-1, java.version=1.7.0_60, java.vendor=Oracle Corporation} 12 no deletions 13 test: open reader.........OK 14 test: check integrity.....OK 15 test: check live docs.....OK 16 test: fields..............OK [3 fields] 17 test: field norms.........OK [1 fields] 18 test: terms, freq, prox...OK [36091 terms; 54003 terms/docs pairs; 18001 tokens] 19 test: stored fields.......OK [54003 total field count; avg 3 fields per doc] 20 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 21 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 22 23 2 of 7: name=_l docCount=1000 24 codec=Lucene46 25 compound=false 26 numFiles=10 27 size (MB)=0.028 28 diagnostics = {timestamp=1411221019406, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 29 no deletions 30 test: open reader.........OK 31 test: check integrity.....OK 32 test: check live docs.....OK 33 test: fields..............OK [3 fields] 34 test: field norms.........OK [1 fields] 35 test: terms, freq, prox...OK [2002 terms; 3000 terms/docs pairs; 1000 tokens] 36 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 37 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 38 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 39 40 3 of 7: name=_m docCount=1000 41 codec=Lucene46 42 compound=false 43 numFiles=10 44 size (MB)=0.028 45 diagnostics = {timestamp=1411221019478, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 46 no deletions 47 test: open reader.........OK 48 test: check integrity.....OK 49 test: check live docs.....OK 50 test: fields..............OK [3 fields] 51 test: field norms.........OK [1 fields] 52 test: terms, freq, prox...OK [2002 terms; 3000 terms/docs pairs; 1000 tokens] 53 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 54 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 55 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 56 57 4 of 7: name=_n docCount=1000 58 codec=Lucene46 59 compound=false 60 numFiles=10 61 size (MB)=0.028 62 diagnostics = {timestamp=1411221019552, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 63 no deletions 64 test: open reader.........OK 65 test: check integrity.....OK 66 test: check live docs.....OK 67 test: fields..............OK [3 fields] 68 test: field norms.........OK [1 fields] 69 test: terms, freq, prox...OK [2002 terms; 3000 terms/docs pairs; 1000 tokens] 70 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 71 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 72 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 73 74 5 of 7: name=_o docCount=1000 75 codec=Lucene46 76 compound=false 77 numFiles=10 78 size (MB)=0.028 79 diagnostics = {timestamp=1411221019629, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 80 no deletions 81 test: open reader.........OK 82 test: check integrity.....OK 83 test: check live docs.....OK 84 test: fields..............OK [3 fields] 85 test: field norms.........OK [1 fields] 86 test: terms, freq, prox...OK [2002 terms; 3000 terms/docs pairs; 1000 tokens] 87 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 88 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 89 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 90 91 6 of 7: name=_p docCount=1000 92 codec=Lucene46 93 compound=false 94 numFiles=10 95 size (MB)=0.028 96 diagnostics = {timestamp=1411221019739, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 97 no deletions 98 test: open reader.........OK 99 test: check integrity.....OK 100 test: check live docs.....OK 101 test: fields..............OK [3 fields] 102 test: field norms.........OK [1 fields] 103 test: terms, freq, prox...OK [2002 terms; 3000 terms/docs pairs; 1000 tokens] 104 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 105 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 106 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 107 108 7 of 7: name=_q docCount=1000 109 codec=Lucene46 110 compound=false 111 numFiles=10 112 size (MB)=0.027 113 diagnostics = {timestamp=1411221019863, os=Mac OS X, os.version=10.9.4, source=flush, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, os.arch=x86_64, java.version=1.7.0_60, java.vendor=Oracle Corporation} 114 no deletions 115 test: open reader.........OK 116 test: check integrity.....OK 117 test: check live docs.....OK 118 test: fields..............OK [3 fields] 119 test: field norms.........OK [1 fields] 120 test: terms, freq, prox...OK [2001 terms; 3000 terms/docs pairs; 1000 tokens] 121 test: stored fields.......OK [3000 total field count; avg 3 fields per doc] 122 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 123 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 124 125 No problems were detected with this index.
由于我的索引文件是正常的,那么通过网上的例子来查看下错误的情况下是什么样子的,并且-fix是怎么样子的效果:
来自网友:http://blog.csdn.net/laigood/article/details/8296678
1 Segments file=segments_2cg numSegments=26 version=3.6.1 format=FORMAT_3_1 [Lucene 3.1+] userData={translog_id=1347536741715} 2 1 of 26: name=_59ct docCount=4711242 3 compound=false 4 hasProx=true 5 numFiles=9 6 size (MB)=6,233.694 7 diagnostics = {mergeFactor=13, os.version=2.6.32-71.el6.x86_64, os=Linux, lucene.version=3.6.1 1362471 - thetaphi - 2012-07-17 12:40:12, source=merge, os.arch=amd64, mergeMaxNumSegments=-1, java.version=1.6.0_24, java.vendor=Sun Microsystems Inc.} 8 has deletions [delFileName=_59ct_1b.del] 9 test: open reader.........OK [3107 deleted docs] 10 test: fields..............OK [25 fields] 11 test: field norms.........OK [10 fields] 12 test: terms, freq, prox...OK [36504908 terms; 617641081 terms/docs pairs; 742052507 tokens] 13 test: stored fields.......ERROR [read past EOF: MMapIndexInput(path="/usr/local/sas/escluster/data/cluster/nodes/0/indices/index/5/index/_59ct.fdt")] 14 java.io.EOFException: read past EOF: MMapIndexInput(path="/usr/local/sas/escluster/data/cluster/nodes/0/indices/index/5/index/_59ct.fdt") 15 at org.apache.lucene.store.MMapDirectory$MMapIndexInput.readBytes(MMapDirectory.java:307) 16 at org.apache.lucene.index.FieldsReader.addField(FieldsReader.java:400) 17 at org.apache.lucene.index.FieldsReader.doc(FieldsReader.java:253) 18 at org.apache.lucene.index.SegmentReader.document(SegmentReader.java:492) 19 at org.apache.lucene.index.IndexReader.document(IndexReader.java:1138) 20 at org.apache.lucene.index.CheckIndex.testStoredFields(CheckIndex.java:852) 21 at org.apache.lucene.index.CheckIndex.checkIndex(CheckIndex.java:581) 22 at org.apache.lucene.index.CheckIndex.main(CheckIndex.java:1064) 23 test: term vectors........OK [0 total vector count; avg 0 term/freq vector fields per doc] 24 FAILED 25 WARNING: fixIndex() would remove reference to this segment; full exception: 26 java.lang.RuntimeException: Stored Field test failed 27 at org.apache.lucene.index.CheckIndex.checkIndex(CheckIndex.java:593) 28 at org.apache.lucene.index.CheckIndex.main(CheckIndex.java:1064) 29 30 31 WARNING: 1 broken segments (containing 4708135 documents) detected 32 WARNING: 4708135 documents will be lost
1 java -cp lucene-core-3.6.1.jar -ea:org.apache.lucene... org.apache.lucene.index.CheckIndex /usr/local/sas/escluster/data/cluster/nodes/0/indices/index/5/index/ -fix 2 NOTE: will write new segments file in 5 seconds; this will remove 4708135 docs from the index. THIS IS YOUR LAST CHANCE TO CTRL+C! 3 5... 4 4... 5 3... 6 2... 7 1... 8 Writing... 9 OK 10 Wrote new segments file "segments_2ch"
还可以通过检查某一个segment:
1 userdeMacBook-Pro:lib rcf$ java -cp lucene-core-4.8-SNAPSHOT.jar -ea:org.apache.lucene.index... org.apache.lucene.index.CheckIndex ../../../../../../solr/Solr/test/data/index -segment _9 2 3 Opening index @ ../../../../../../solr/Solr/test/data/index 4 5 Segments file=segments_r numSegments=7 version=4.8 format= userData={commitTimeMSec=1411221019854} 6 7 Checking only these segments: _9: 8 No problems were detected with this index.
还可以通过-verbose查看更多详细信息,这里就不在详述。
2. CheckIndex的源码
接着我们再来学习下CheckIndex的源码是怎么来实现以上功能的,检查索引的功能主要集中在checkindex()函数上,
1 public Status checkIndex(List<String> onlySegments) throws IOException { 2 ... 3 final int numSegments = sis.size(); //获取segment个数 4 final String segmentsFileName = sis.getSegmentsFileName(); //获取segment_N名字 5 // note: we only read the format byte (required preamble) here! 6 IndexInput input = null; 7 try { 8 input = dir.openInput(segmentsFileName, IOContext.READONCE);//读取segment_N文件 9 } catch (Throwable t) { 10 msg(infoStream, "ERROR: could not open segments file in directory"); 11 if (infoStream != null) 12 t.printStackTrace(infoStream); 13 result.cantOpenSegments = true; 14 return result; 15 } 16 int format = 0; 17 try { 18 format = input.readInt(); //读取segment_N version 19 } catch (Throwable t) { 20 msg(infoStream, "ERROR: could not read segment file version in directory"); 21 if (infoStream != null) 22 t.printStackTrace(infoStream); 23 result.missingSegmentVersion = true; 24 return result; 25 } finally { 26 if (input != null) 27 input.close(); 28 } 29 30 String sFormat = ""; 31 boolean skip = false; 32 33 result.segmentsFileName = segmentsFileName;//segment_N名字 34 result.numSegments = numSegments; //segment个数 35 result.userData = sis.getUserData(); //获取user信息,如userData={commitTimeMSec=1411221019854} 36 String userDataString; 37 if (sis.getUserData().size() > 0) { 38 userDataString = " userData=" + sis.getUserData(); 39 } else { 40 userDataString = ""; 41 } 42 //获取版本信息,如version=4.8 43 String versionString = null; 44 if (oldSegs != null) { 45 if (foundNonNullVersion) { 46 versionString = "versions=[" + oldSegs + " .. " + newest + "]"; 47 } else { 48 versionString = "version=" + oldSegs; 49 } 50 } else { 51 versionString = oldest.equals(newest) ? ( "version=" + oldest ) : ("versions=[" + oldest + " .. " + newest + "]"); 52 } 53 54 msg(infoStream, "Segments file=" + segmentsFileName + " numSegments=" + numSegments 55 + " " + versionString + " format=" + sFormat + userDataString); 56 57 if (onlySegments != null) { 58 result.partial = true; 59 if (infoStream != null) { 60 infoStream.print("\nChecking only these segments:"); 61 for (String s : onlySegments) { 62 infoStream.print(" " + s); 63 } 64 } 65 result.segmentsChecked.addAll(onlySegments); 66 msg(infoStream, ":"); 67 } 68 69 if (skip) { 70 msg(infoStream, "\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"); 71 result.toolOutOfDate = true; 72 return result; 73 } 74 75 76 result.newSegments = sis.clone(); 77 result.newSegments.clear(); 78 result.maxSegmentName = -1; 79 //开始遍历segment,检查segment 80 for(int i=0;i<numSegments;i++) { 81 final SegmentCommitInfo info = sis.info(i); //获取segment信息 82 int segmentName = Integer.parseInt(info.info.name.substring(1), Character.MAX_RADIX); 83 if (segmentName > result.maxSegmentName) { 84 result.maxSegmentName = segmentName; 85 } 86 if (onlySegments != null && !onlySegments.contains(info.info.name)) { 87 continue; 88 } 89 Status.SegmentInfoStatus segInfoStat = new Status.SegmentInfoStatus(); 90 result.segmentInfos.add(segInfoStat); 91 //获取segments编号,名字,document个数,如下信息 1 of 7: name=_k docCount=18001 92 msg(infoStream, " " + (1+i) + " of " + numSegments + ": name=" + info.info.name + " docCount=" + info.info.getDocCount()); 93 segInfoStat.name = info.info.name; 94 segInfoStat.docCount = info.info.getDocCount(); 95 96 final String version = info.info.getVersion(); 97 if (info.info.getDocCount() <= 0 && version != null && versionComparator.compare(version, "4.5") >= 0) { 98 throw new RuntimeException("illegal number of documents: maxDoc=" + info.info.getDocCount()); 99 } 100 101 int toLoseDocCount = info.info.getDocCount(); 102 103 AtomicReader reader = null; 104 105 try { 106 final Codec codec = info.info.getCodec(); //获取codec信息,如codec=Lucene46 107 msg(infoStream, " codec=" + codec); 108 segInfoStat.codec = codec; 109 msg(infoStream, " compound=" + info.info.getUseCompoundFile());//获取复合文档格式标志位:compound=false 110 segInfoStat.compound = info.info.getUseCompoundFile(); 111 msg(infoStream, " numFiles=" + info.files().size()); 112 segInfoStat.numFiles = info.files().size(); //获取段内文件个数numFiles=10 113 segInfoStat.sizeMB = info.sizeInBytes()/(1024.*1024.);//获取segment大小如size (MB)=0.493 114 if (info.info.getAttribute(Lucene3xSegmentInfoFormat.DS_OFFSET_KEY) == null) { 115 // don't print size in bytes if its a 3.0 segment with shared docstores 116 msg(infoStream, " size (MB)=" + nf.format(segInfoStat.sizeMB)); 117 } 118 //获取诊断信息,diagnostics = {timestamp=1411221019346, os=Mac OS X, os.version=10.9.4, mergeFactor=10, 119 //source=merge, lucene.version=4.8-SNAPSHOT Unversioned directory - rcf - 2014-09-20 21:11:36, 120 //os.arch=x86_64, mergeMaxNumSegments=-1, java.version=1.7.0_60, java.vendor=Oracle Corporation} 121 Map<String,String> diagnostics = info.info.getDiagnostics(); 122 segInfoStat.diagnostics = diagnostics; 123 if (diagnostics.size() > 0) { 124 msg(infoStream, " diagnostics = " + diagnostics); 125 } 126 //判断是否有document删除,如输出no deletions 或者 has deletions [delFileName=_59ct_1b.del] 127 if (!info.hasDeletions()) { 128 msg(infoStream, " no deletions"); 129 segInfoStat.hasDeletions = false; 130 } 131 else{ 132 msg(infoStream, " has deletions [delGen=" + info.getDelGen() + "]"); 133 segInfoStat.hasDeletions = true; 134 segInfoStat.deletionsGen = info.getDelGen(); 135 } 136 137 //通过新建SegmentReader对象来检查是否能获取索引reader,如果扔出错误说明不能打开。例如输出test: open reader.........OK, 138 if (infoStream != null) 139 infoStream.print(" test: open reader........."); 140 reader = new SegmentReader(info, DirectoryReader.DEFAULT_TERMS_INDEX_DIVISOR, IOContext.DEFAULT); 141 msg(infoStream, "OK"); 142 143 segInfoStat.openReaderPassed = true; 144 //通过checkIntegrity来检查文件的完整性,例如输出:test: check integrity.....OK 145 //checkIntegrity函数是通过CodecUtil.checksumEntireFile()实现来检查文件的完整。 146 if (infoStream != null) 147 infoStream.print(" test: check integrity....."); 148 reader.checkIntegrity(); 149 msg(infoStream, "OK"); 150 151 //检查document数量是否正确,如果有删除的document时候,通过reader.numDocs() 152 //== info.info.getDocCount() - info.getDelCount()以及统计以及检测livedocs的个数是否于reader.numDocs() 一致。 153 //注意:没有删除的document时候,livedocs为null; 154 //当没有删除的document时候,reader.maxDoc() == info.info.getDocCount()来检查是否一致。 155 //输出结果比如:test: check live docs.....OK 156 //solr的管理界面可以显示: 现有document,删除的document以及所有的document数量,获取方法就是如下。 157 if (infoStream != null) 158 infoStream.print(" test: check live docs....."); 159 final int numDocs = reader.numDocs(); 160 toLoseDocCount = numDocs; 161 if (reader.hasDeletions()) { 162 if (reader.numDocs() != info.info.getDocCount() - info.getDelCount()) { 163 throw new RuntimeException("delete count mismatch: info=" + (info.info.getDocCount() - info.getDelCount()) + " vs reader=" + reader.numDocs()); 164 } 165 if ((info.info.getDocCount()-reader.numDocs()) > reader.maxDoc()) { 166 throw new RuntimeException("too many deleted docs: maxDoc()=" + reader.maxDoc() + " vs del count=" + (info.info.getDocCount()-reader.numDocs())); 167 } 168 if (info.info.getDocCount() - numDocs != info.getDelCount()) { 169 throw new RuntimeException("delete count mismatch: info=" + info.getDelCount() + " vs reader=" + (info.info.getDocCount() - numDocs)); 170 } 171 Bits liveDocs = reader.getLiveDocs(); 172 if (liveDocs == null) { 173 throw new RuntimeException("segment should have deletions, but liveDocs is null"); 174 } else { 175 int numLive = 0; 176 for (int j = 0; j < liveDocs.length(); j++) { 177 if (liveDocs.get(j)) { 178 numLive++; 179 } 180 } 181 if (numLive != numDocs) { 182 throw new RuntimeException("liveDocs count mismatch: info=" + numDocs + ", vs bits=" + numLive); 183 } 184 } 185 186 segInfoStat.numDeleted = info.info.getDocCount() - numDocs; 187 msg(infoStream, "OK [" + (segInfoStat.numDeleted) + " deleted docs]"); 188 } else { 189 if (info.getDelCount() != 0) { 190 throw new RuntimeException("delete count mismatch: info=" + info.getDelCount() + " vs reader=" + (info.info.getDocCount() - numDocs)); 191 } 192 Bits liveDocs = reader.getLiveDocs(); 193 if (liveDocs != null) { 194 // its ok for it to be non-null here, as long as none are set right? 195 // 这里好像有点问题,当delete document不存在时候,liveDocs应该为null。 196 for (int j = 0; j < liveDocs.length(); j++) { 197 if (!liveDocs.get(j)) { 198 throw new RuntimeException("liveDocs mismatch: info says no deletions but doc " + j + " is deleted."); 199 } 200 } 201 } 202 msg(infoStream, "OK"); 203 } 204 if (reader.maxDoc() != info.info.getDocCount()) { 205 throw new RuntimeException("SegmentReader.maxDoc() " + reader.maxDoc() + " != SegmentInfos.docCount " + info.info.getDocCount()); 206 } 207 208 // Test getFieldInfos() 209 // 获取域状态以及数量 如:test: fields..............OK [3 fields] 210 if (infoStream != null) { 211 infoStream.print(" test: fields.............."); 212 } 213 FieldInfos fieldInfos = reader.getFieldInfos(); 214 msg(infoStream, "OK [" + fieldInfos.size() + " fields]"); 215 segInfoStat.numFields = fieldInfos.size(); 216 217 // Test Field Norms 218 // 获取Field Norms的状态以及数量 test: field norms.........OK [1 fields] 219 segInfoStat.fieldNormStatus = testFieldNorms(reader, infoStream); 220 221 // Test the Term Index 222 // 获取Field Index的状态以及数量 test: terms, freq, prox...OK [36091 terms; 54003 terms/docs pairs; 18001 tokens] 223 segInfoStat.termIndexStatus = testPostings(reader, infoStream, verbose); 224 225 // Test Stored Fields 226 // 获取Stored Field 的状态 test: stored fields.......OK [54003 total field count; avg 3 fields per doc] 227 segInfoStat.storedFieldStatus = testStoredFields(reader, infoStream); 228 229 // Test Term Vectors 230 // 获取Term Field 的状态 test: stored fields.......OK [54003 total field count; avg 3 fields per doc] 231 segInfoStat.termVectorStatus = testTermVectors(reader, infoStream, verbose, crossCheckTermVectors); 232 233 // 获取Doc Value 的状态 test: docvalues...........OK [0 docvalues fields; 0 BINARY; 0 NUMERIC; 0 SORTED; 0 SORTED_SET] 234 segInfoStat.docValuesStatus = testDocValues(reader, infoStream); 235 236 // Rethrow the first exception we encountered 237 // This will cause stats for failed segments to be incremented properly 238 if (segInfoStat.fieldNormStatus.error != null) { 239 throw new RuntimeException("Field Norm test failed"); 240 } else if (segInfoStat.termIndexStatus.error != null) { 241 throw new RuntimeException("Term Index test failed"); 242 } else if (segInfoStat.storedFieldStatus.error != null) { 243 throw new RuntimeException("Stored Field test failed"); 244 } else if (segInfoStat.termVectorStatus.error != null) { 245 throw new RuntimeException("Term Vector test failed"); 246 } else if (segInfoStat.docValuesStatus.error != null) { 247 throw new RuntimeException("DocValues test failed"); 248 } 249 250 msg(infoStream, ""); 251 252 } catch (Throwable t) { 253 msg(infoStream, "FAILED"); 254 String comment; 255 comment = "fixIndex() would remove reference to this segment"; 256 msg(infoStream, " WARNING: " + comment + "; full exception:"); 257 if (infoStream != null) 258 t.printStackTrace(infoStream); 259 msg(infoStream, ""); 260 result.totLoseDocCount += toLoseDocCount; 261 result.numBadSegments++; 262 continue; 263 } finally { 264 if (reader != null) 265 reader.close(); 266 } 267 268 // Keeper 269 result.newSegments.add(info.clone()); 270 } 271 272 if (0 == result.numBadSegments) { 273 result.clean = true; 274 } else 275 msg(infoStream, "WARNING: " + result.numBadSegments + " broken segments (containing " + result.totLoseDocCount + " documents) detected"); 276 277 if ( ! (result.validCounter = (result.maxSegmentName < sis.counter))) { 278 result.clean = false; 279 result.newSegments.counter = result.maxSegmentName + 1; 280 msg(infoStream, "ERROR: Next segment name counter " + sis.counter + " is not greater than max segment name " + result.maxSegmentName); 281 } 282 283 if (result.clean) { 284 msg(infoStream, "No problems were detected with this index.\n"); 285 } 286 287 return result; 288 }
其中关于testFieldNorms这几个的源码明天继续学习