TermInfosReader.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:7k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2004 The Apache Software Foundation
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. using System;
  17. using Directory = Lucene.Net.Store.Directory;
  18. namespace Lucene.Net.Index
  19. {
  20. /// <summary>This stores a monotonically increasing set of <Term, TermInfo> pairs in a
  21. /// Directory.  Pairs are accessed either by Term or by ordinal position the
  22. /// set.  
  23. /// </summary>
  24. public sealed class TermInfosReader
  25. {
  26. private Directory directory;
  27. private System.String segment;
  28. private FieldInfos fieldInfos;
  29. private System.LocalDataStoreSlot enumerators = System.Threading.Thread.AllocateDataSlot();
  30. private SegmentTermEnum origEnum;
  31. private long size;
  32. private Term[] indexTerms = null;
  33. private TermInfo[] indexInfos;
  34. private long[] indexPointers;
  35. private SegmentTermEnum indexEnum;
  36. public /*internal*/ TermInfosReader(Directory dir, System.String seg, FieldInfos fis)
  37. {
  38. directory = dir;
  39. segment = seg;
  40. fieldInfos = fis;
  41. origEnum = new SegmentTermEnum(directory.OpenInput(segment + ".tis"), fieldInfos, false);
  42. size = origEnum.size;
  43. indexEnum = new SegmentTermEnum(directory.OpenInput(segment + ".tii"), fieldInfos, true);
  44. }
  45. ~TermInfosReader()
  46. {
  47.             try
  48.             {
  49.                 // patch for pre-1.4.2 JVMs, whose ThreadLocals leak
  50.                 System.Threading.Thread.SetData(enumerators, null);     // {{Aroush-1.9}} is this required for .NET ?!
  51.             }
  52.             catch (Exception)
  53.             {
  54.             }
  55. }
  56. public int GetSkipInterval()
  57. {
  58. return origEnum.skipInterval;
  59. }
  60. public /*internal*/ void  Close()
  61. {
  62. if (origEnum != null)
  63. origEnum.Close();
  64. if (indexEnum != null)
  65. indexEnum.Close();
  66. }
  67. /// <summary>Returns the number of term/value pairs in the set. </summary>
  68. internal long Size()
  69. {
  70. return size;
  71. }
  72. private SegmentTermEnum GetEnum()
  73. {
  74. SegmentTermEnum termEnum = (SegmentTermEnum) System.Threading.Thread.GetData(enumerators);
  75. if (termEnum == null)
  76. {
  77. termEnum = Terms();
  78. System.Threading.Thread.SetData(enumerators, termEnum);
  79. }
  80. return termEnum;
  81. }
  82. private void  EnsureIndexIsRead()
  83. {
  84. lock (this)
  85. {
  86. if (indexTerms != null)
  87. // index already read
  88. return ; // do nothing
  89. try
  90. {
  91. int indexSize = (int) indexEnum.size; // otherwise read index
  92. indexTerms = new Term[indexSize];
  93. indexInfos = new TermInfo[indexSize];
  94. indexPointers = new long[indexSize];
  95. for (int i = 0; indexEnum.Next(); i++)
  96. {
  97. indexTerms[i] = indexEnum.Term();
  98. indexInfos[i] = indexEnum.TermInfo();
  99. indexPointers[i] = indexEnum.indexPointer;
  100. }
  101. }
  102. finally
  103. {
  104. indexEnum.Close();
  105. indexEnum = null;
  106. }
  107. }
  108. }
  109. /// <summary>Returns the offset of the greatest index entry which is less than or equal to term.</summary>
  110. private int GetIndexOffset(Term term)
  111. {
  112. int lo = 0; // binary search indexTerms[]
  113. int hi = indexTerms.Length - 1;
  114. while (hi >= lo)
  115. {
  116. int mid = (lo + hi) >> 1;
  117. int delta = term.CompareTo(indexTerms[mid]);
  118. if (delta < 0)
  119. hi = mid - 1;
  120. else if (delta > 0)
  121. lo = mid + 1;
  122. else
  123. return mid;
  124. }
  125. return hi;
  126. }
  127. private void  SeekEnum(int indexOffset)
  128. {
  129. GetEnum().Seek(indexPointers[indexOffset], (indexOffset * GetEnum().indexInterval) - 1, indexTerms[indexOffset], indexInfos[indexOffset]);
  130. }
  131. /// <summary>Returns the TermInfo for a Term in the set, or null. </summary>
  132. public /*internal*/ TermInfo Get(Term term)
  133. {
  134. if (size == 0)
  135. return null;
  136. EnsureIndexIsRead();
  137. // optimize sequential access: first try scanning cached enum w/o seeking
  138. SegmentTermEnum enumerator = GetEnum();
  139. if (enumerator.Term() != null && ((enumerator.Prev() != null && term.CompareTo(enumerator.Prev()) > 0) || term.CompareTo(enumerator.Term()) >= 0))
  140. {
  141. int enumOffset = (int) (enumerator.position / enumerator.indexInterval) + 1;
  142. if (indexTerms.Length == enumOffset || term.CompareTo(indexTerms[enumOffset]) < 0)
  143. return ScanEnum(term); // no need to seek
  144. }
  145. // random-access: must seek
  146. SeekEnum(GetIndexOffset(term));
  147. return ScanEnum(term);
  148. }
  149. /// <summary>Scans within block for matching term. </summary>
  150. private TermInfo ScanEnum(Term term)
  151. {
  152. SegmentTermEnum enumerator = GetEnum();
  153. enumerator.ScanTo(term);
  154. if (enumerator.Term() != null && term.CompareTo(enumerator.Term()) == 0)
  155. return enumerator.TermInfo();
  156. else
  157. return null;
  158. }
  159. /// <summary>Returns the nth term in the set. </summary>
  160. internal Term Get(int position)
  161. {
  162. if (size == 0)
  163. return null;
  164. SegmentTermEnum enumerator = GetEnum();
  165. if (enumerator != null && enumerator.Term() != null && position >= enumerator.position && position < (enumerator.position + enumerator.indexInterval))
  166. return ScanEnum(position); // can avoid seek
  167. SeekEnum(position / enumerator.indexInterval); // must seek
  168. return ScanEnum(position);
  169. }
  170. private Term ScanEnum(int position)
  171. {
  172. SegmentTermEnum enumerator = GetEnum();
  173. while (enumerator.position < position)
  174. if (!enumerator.Next())
  175. return null;
  176. return enumerator.Term();
  177. }
  178. /// <summary>Returns the position of a Term in the set or -1. </summary>
  179. internal long GetPosition(Term term)
  180. {
  181. if (size == 0)
  182. return - 1;
  183. EnsureIndexIsRead();
  184. int indexOffset = GetIndexOffset(term);
  185. SeekEnum(indexOffset);
  186. SegmentTermEnum enumerator = GetEnum();
  187. while (term.CompareTo(enumerator.Term()) > 0 && enumerator.Next())
  188. {
  189. }
  190. if (term.CompareTo(enumerator.Term()) == 0)
  191. return enumerator.position;
  192. else
  193. return - 1;
  194. }
  195. /// <summary>Returns an enumeration of all the Terms and TermInfos in the set. </summary>
  196. public SegmentTermEnum Terms()
  197. {
  198. return (SegmentTermEnum) origEnum.Clone();
  199. }
  200. /// <summary>Returns an enumeration of terms starting at or after the named term. </summary>
  201. public SegmentTermEnum Terms(Term term)
  202. {
  203. Get(term);
  204. return (SegmentTermEnum) GetEnum().Clone();
  205. }
  206. }
  207. }