19 using Lucene.Net.Support;
20 using Lucene.Net.Util;
21 using Lucene.Net.Util.Cache;
24 namespace Lucene.Net.Index
35 private readonly String segment;
38 private bool isDisposed;
41 private readonly SegmentTermEnum origEnum;
42 private readonly
long size;
44 private readonly
Term[] indexTerms;
45 private readonly
TermInfo[] indexInfos;
46 private readonly
long[] indexPointers;
48 private readonly
int totalIndexInterval;
50 private const int DEFAULT_CACHE_SIZE = 1024;
53 private sealed
class ThreadResources
55 internal SegmentTermEnum termEnum;
58 internal Cache<Term, TermInfo> termInfoCache;
65 if (indexDivisor < 1 && indexDivisor != - 1)
67 throw new System.ArgumentException(
"indexDivisor must be -1 (don't load terms index) or greater than 0: got " + indexDivisor);
80 if (indexDivisor != - 1)
83 totalIndexInterval = origEnum.indexInterval * indexDivisor;
88 int indexSize = 1 + ((int) indexEnum.size - 1) / indexDivisor;
90 indexTerms =
new Term[indexSize];
91 indexInfos =
new TermInfo[indexSize];
92 indexPointers =
new long[indexSize];
94 for (
int i = 0; indexEnum.Next(); i++)
96 indexTerms[i] = indexEnum.Term;
97 indexInfos[i] = indexEnum.TermInfo();
98 indexPointers[i] = indexEnum.indexPointer;
100 for (
int j = 1; j < indexDivisor; j++)
101 if (!indexEnum.Next())
113 totalIndexInterval = - 1;
116 indexPointers = null;
134 public int SkipInterval
136 get {
return origEnum.skipInterval; }
139 public int MaxSkipLevels
141 get {
return origEnum.maxSkipLevels; }
144 public void Dispose()
146 if (isDisposed)
return;
149 if (origEnum != null)
151 threadResources.Dispose();
162 private ThreadResources GetThreadResources()
164 ThreadResources resources = threadResources.Get();
165 if (resources == null)
167 resources =
new ThreadResources
168 {termEnum = Terms(), termInfoCache =
new SimpleLRUCache<Term, TermInfo>(DEFAULT_CACHE_SIZE)};
170 threadResources.Set(resources);
177 private int GetIndexOffset(
Term term)
180 int hi = indexTerms.Length - 1;
185 int delta = term.CompareTo(indexTerms[mid]);
196 private void SeekEnum(SegmentTermEnum enumerator,
int indexOffset)
198 enumerator.Seek(indexPointers[indexOffset], ((
long)indexOffset * totalIndexInterval) - 1, indexTerms[indexOffset], indexInfos[indexOffset]);
204 return Get(term,
true);
216 ThreadResources resources = GetThreadResources();
217 Cache<Term, TermInfo> cache = null;
221 cache = resources.termInfoCache;
223 ti = cache.Get(term);
231 SegmentTermEnum enumerator = resources.termEnum;
232 if (enumerator.Term != null && ((enumerator.Prev() != null && term.CompareTo(enumerator.Prev()) > 0) || term.CompareTo(enumerator.Term) >= 0))
234 int enumOffset = (int) (enumerator.position / totalIndexInterval) + 1;
235 if (indexTerms.Length == enumOffset || term.CompareTo(indexTerms[enumOffset]) < 0)
239 int numScans = enumerator.ScanTo(term);
240 if (enumerator.Term != null && term.CompareTo(enumerator.Term) == 0)
242 ti = enumerator.TermInfo();
243 if (cache != null && numScans > 1)
263 SeekEnum(enumerator, GetIndexOffset(term));
264 enumerator.ScanTo(term);
265 if (enumerator.Term != null && term.CompareTo(enumerator.Term) == 0)
267 ti = enumerator.TermInfo();
280 private void EnsureIndexIsRead()
282 if (indexTerms == null)
284 throw new SystemException(
"terms index was not loaded when this reader was created");
289 internal long GetPosition(
Term term)
295 int indexOffset = GetIndexOffset(term);
297 SegmentTermEnum enumerator = GetThreadResources().termEnum;
298 SeekEnum(enumerator, indexOffset);
300 while (term.CompareTo(enumerator.Term) > 0 && enumerator.Next())
304 if (term.CompareTo(enumerator.Term) == 0)
305 return enumerator.position;
311 public SegmentTermEnum Terms()
313 return (SegmentTermEnum) origEnum.Clone();
317 public SegmentTermEnum Terms(
Term term)
322 return (SegmentTermEnum) GetThreadResources().termEnum.Clone();