Thumbnail file hits. Based on a patch from D Bera
[beagle.git] / beagled / Lucene.Net / Index / TermInfosReader.cs
bloba722c83575332ab9a7fb7a3ac6aff028fca2e7c8
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.
16 using System;
17 using Directory = Lucene.Net.Store.Directory;
18 namespace Lucene.Net.Index
21 /// <summary>This stores a monotonically increasing set of <Term, TermInfo> pairs in a
22 /// Directory. Pairs are accessed either by Term or by ordinal position the
23 /// set.
24 /// </summary>
26 sealed public class TermInfosReader
28 private Directory directory;
29 private System.String segment;
30 private FieldInfos fieldInfos;
32 private System.LocalDataStoreSlot enumerators = System.Threading.Thread.AllocateDataSlot();
33 private SegmentTermEnum origEnum;
34 private long size;
36 public /*internal*/ TermInfosReader(Directory dir, System.String seg, FieldInfos fis)
38 directory = dir;
39 segment = seg;
40 fieldInfos = fis;
42 origEnum = new SegmentTermEnum(directory.OpenFile(segment + ".tis"), fieldInfos, false);
43 size = origEnum.size;
44 ReadIndex();
47 public int GetSkipInterval()
49 return origEnum.skipInterval;
52 public /*internal*/ void Close()
54 if (origEnum != null)
55 origEnum.Close();
58 /// <summary>Returns the number of term/value pairs in the set. </summary>
59 internal long Size()
61 return size;
64 private SegmentTermEnum GetEnum()
66 SegmentTermEnum termEnum = (SegmentTermEnum) System.Threading.Thread.GetData(enumerators);
67 if (termEnum == null)
69 termEnum = Terms();
70 System.Threading.Thread.SetData(enumerators, termEnum);
72 return termEnum;
75 internal Term[] indexTerms = null;
76 internal TermInfo[] indexInfos;
77 internal long[] indexPointers;
79 private void ReadIndex()
81 SegmentTermEnum indexEnum = new SegmentTermEnum(directory.OpenFile(segment + ".tii"), fieldInfos, true);
82 try
84 int indexSize = (int) indexEnum.size;
86 indexTerms = new Term[indexSize];
87 indexInfos = new TermInfo[indexSize];
88 indexPointers = new long[indexSize];
90 for (int i = 0; indexEnum.Next(); i++)
92 indexTerms[i] = indexEnum.Term();
93 indexInfos[i] = indexEnum.TermInfo();
94 indexPointers[i] = indexEnum.indexPointer;
97 finally
99 indexEnum.Close();
103 /// <summary>Returns the offset of the greatest index entry which is less than or equal to term.</summary>
104 private int GetIndexOffset(Term term)
106 int lo = 0; // binary search indexTerms[]
107 int hi = indexTerms.Length - 1;
109 while (hi >= lo)
111 int mid = (lo + hi) >> 1;
112 int delta = term.CompareTo(indexTerms[mid]);
113 if (delta < 0)
114 hi = mid - 1;
115 else if (delta > 0)
116 lo = mid + 1;
117 else
118 return mid;
120 return hi;
123 private void SeekEnum(int indexOffset)
125 GetEnum().Seek(indexPointers[indexOffset], (indexOffset * GetEnum().indexInterval) - 1, indexTerms[indexOffset], indexInfos[indexOffset]);
128 /// <summary>Returns the TermInfo for a Term in the set, or null. </summary>
129 public /*internal*/ TermInfo Get(Term term)
131 if (size == 0)
132 return null;
134 // optimize sequential access: first try scanning cached enum w/o seeking
135 SegmentTermEnum enumerator = GetEnum();
136 if (enumerator.Term() != null && ((enumerator.Prev () != null && term.CompareTo(enumerator.Prev ()) > 0) || term.CompareTo(enumerator.Term()) >= 0))
138 int enumOffset = (int) (enumerator.position / enumerator.indexInterval) + 1;
139 if (indexTerms.Length == enumOffset || term.CompareTo(indexTerms[enumOffset]) < 0)
140 return ScanEnum(term); // no need to seek
143 // random-access: must seek
144 SeekEnum(GetIndexOffset(term));
145 return ScanEnum(term);
148 /// <summary>Scans within block for matching term. </summary>
149 private TermInfo ScanEnum(Term term)
151 SegmentTermEnum enumerator = GetEnum();
152 enumerator.ScanTo (term);
154 if (enumerator.Term() != null && term.CompareTo(enumerator.Term()) == 0)
155 return enumerator.TermInfo();
156 else
157 return null;
160 /// <summary>Returns the nth term in the set. </summary>
161 internal Term Get(int position)
163 if (size == 0)
164 return null;
166 SegmentTermEnum enumerator = GetEnum();
167 if (enumerator != null && enumerator.Term() != null && position >= enumerator.position && position < (enumerator.position + enumerator.indexInterval))
168 return ScanEnum(position); // can avoid seek
170 SeekEnum(position / enumerator.indexInterval); // must seek
171 return ScanEnum(position);
174 private Term ScanEnum(int position)
176 SegmentTermEnum enumerator = GetEnum();
177 while (enumerator.position < position)
178 if (!enumerator.Next())
179 return null;
181 return enumerator.Term();
184 /// <summary>Returns the position of a Term in the set or -1. </summary>
185 internal long GetPosition(Term term)
187 if (size == 0)
188 return - 1;
190 int indexOffset = GetIndexOffset(term);
191 SeekEnum(indexOffset);
193 SegmentTermEnum enumerator = GetEnum();
194 while (term.CompareTo(enumerator.Term()) > 0 && enumerator.Next())
198 if (term.CompareTo(enumerator.Term()) == 0)
199 return enumerator.position;
200 else
201 return - 1;
204 /// <summary>Returns an enumeration of all the Terms and TermInfos in the set. </summary>
205 public SegmentTermEnum Terms()
207 return (SegmentTermEnum) origEnum.Clone();
210 /// <summary>Returns an enumeration of terms starting at or after the named term. </summary>
211 public SegmentTermEnum Terms(Term term)
213 Get(term);
214 return (SegmentTermEnum) GetEnum().Clone();