forked from apache/lucenenet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTermInfosReaderIndex.cs
More file actions
287 lines (263 loc) · 11.9 KB
/
Copy pathTermInfosReaderIndex.cs
File metadata and controls
287 lines (263 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
using J2N.Numerics;
using J2N.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using JCG = J2N.Collections.Generic;
namespace Lucene.Net.Codecs.Lucene3x
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using BytesRef = Lucene.Net.Util.BytesRef;
using GrowableWriter = Lucene.Net.Util.Packed.GrowableWriter;
using MathUtil = Lucene.Net.Util.MathUtil;
using PackedInt32s = Lucene.Net.Util.Packed.PackedInt32s;
using PagedBytes = Lucene.Net.Util.PagedBytes;
using PagedBytesDataInput = Lucene.Net.Util.PagedBytes.PagedBytesDataInput;
using PagedBytesDataOutput = Lucene.Net.Util.PagedBytes.PagedBytesDataOutput;
using RamUsageEstimator = Lucene.Net.Util.RamUsageEstimator;
using Term = Lucene.Net.Index.Term;
/// <summary>
/// This stores a monotonically increasing set of <c>Term, TermInfo</c> pairs in an
/// index segment. Pairs are accessed either by <see cref="Term"/> or by ordinal position the
/// set. The <see cref="Index.Terms"/> and <see cref="TermInfo"/> are actually serialized and stored into a byte
/// array and pointers to the position of each are stored in a <see cref="int"/> array. </summary>
[Obsolete("Only for reading existing 3.x indexes")]
internal class TermInfosReaderIndex
{
private const int MAX_PAGE_BITS = 18; // 256 KB block
private readonly Term[] fields; // LUCENENET: marked readonly
private readonly int totalIndexInterval; // LUCENENET: marked readonly
private readonly IComparer<BytesRef> comparer = BytesRef.UTF8SortedAsUTF16Comparer; // LUCENENET: marked readonly
private readonly PagedBytesDataInput dataInput;
private readonly PackedInt32s.Reader indexToDataOffset;
private readonly int indexSize;
private readonly int skipInterval;
private readonly long ramBytesUsed;
/// <summary>
/// Loads the segment information at segment load time.
/// </summary>
/// <param name="indexEnum">
/// The term enum. </param>
/// <param name="indexDivisor">
/// The index divisor. </param>
/// <param name="tiiFileLength">
/// The size of the tii file, used to approximate the size of the
/// buffer. </param>
/// <param name="totalIndexInterval">
/// The total index interval. </param>
public TermInfosReaderIndex(SegmentTermEnum indexEnum, int indexDivisor, long tiiFileLength, int totalIndexInterval)
{
this.totalIndexInterval = totalIndexInterval;
indexSize = 1 + ((int)indexEnum.size - 1) / indexDivisor;
skipInterval = indexEnum.skipInterval;
// this is only an initial size, it will be GCed once the build is complete
long initialSize = (long)(tiiFileLength * 1.5) / indexDivisor;
PagedBytes dataPagedBytes = new PagedBytes(EstimatePageBits(initialSize));
PagedBytesDataOutput dataOutput = dataPagedBytes.GetDataOutput();
int bitEstimate = 1 + MathUtil.Log(tiiFileLength, 2);
GrowableWriter indexToTerms = new GrowableWriter(bitEstimate, indexSize, PackedInt32s.DEFAULT);
string currentField = null;
IList<string> fieldStrs = new JCG.List<string>();
int fieldCounter = -1;
for (int i = 0; indexEnum.Next(); i++)
{
Term term = indexEnum.Term();
if (currentField is null || !currentField.Equals(term.Field, StringComparison.Ordinal))
{
currentField = term.Field;
fieldStrs.Add(currentField);
fieldCounter++;
}
TermInfo termInfo = indexEnum.TermInfo();
indexToTerms.Set(i, dataOutput.GetPosition());
dataOutput.WriteVInt32(fieldCounter);
dataOutput.WriteString(term.Text);
dataOutput.WriteVInt32(termInfo.DocFreq);
if (termInfo.DocFreq >= skipInterval)
{
dataOutput.WriteVInt32(termInfo.SkipOffset);
}
dataOutput.WriteVInt64(termInfo.FreqPointer);
dataOutput.WriteVInt64(termInfo.ProxPointer);
dataOutput.WriteVInt64(indexEnum.indexPointer);
for (int j = 1; j < indexDivisor; j++)
{
if (!indexEnum.Next())
{
break;
}
}
}
fields = new Term[fieldStrs.Count];
for (int i = 0; i < fields.Length; i++)
{
fields[i] = new Term(fieldStrs[i]);
}
dataPagedBytes.Freeze(true);
dataInput = dataPagedBytes.GetDataInput();
indexToDataOffset = indexToTerms.Mutable;
ramBytesUsed = fields.Length * (RamUsageEstimator.NUM_BYTES_OBJECT_REF + RamUsageEstimator.ShallowSizeOfInstance(typeof(Term))) + dataPagedBytes.RamBytesUsed() + indexToDataOffset.RamBytesUsed();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int EstimatePageBits(long estSize)
{
return Math.Max(Math.Min(64 - estSize.LeadingZeroCount(), MAX_PAGE_BITS), 4);
}
internal virtual void SeekEnum(SegmentTermEnum enumerator, int indexOffset)
{
PagedBytesDataInput input = (PagedBytesDataInput)dataInput.Clone();
input.SetPosition(indexToDataOffset.Get(indexOffset));
// read the term
int fieldId = input.ReadVInt32();
Term field = fields[fieldId];
Term term = new Term(field.Field, input.ReadString());
// read the terminfo
var termInfo = new TermInfo();
termInfo.DocFreq = input.ReadVInt32();
if (termInfo.DocFreq >= skipInterval)
{
termInfo.SkipOffset = input.ReadVInt32();
}
else
{
termInfo.SkipOffset = 0;
}
termInfo.FreqPointer = input.ReadVInt64();
termInfo.ProxPointer = input.ReadVInt64();
long pointer = input.ReadVInt64();
// perform the seek
enumerator.Seek(pointer, ((long)indexOffset * totalIndexInterval) - 1, term, termInfo);
}
/// <summary>
/// Binary search for the given term.
/// </summary>
/// <param name="term">
/// The term to locate. </param>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
internal virtual int GetIndexOffset(Term term)
{
int lo = 0;
int hi = indexSize - 1;
PagedBytesDataInput input = (PagedBytesDataInput)dataInput.Clone();
BytesRef scratch = new BytesRef();
while (hi >= lo)
{
int mid = (lo + hi) >>> 1;
int delta = CompareTo(term, mid, input, scratch);
if (delta < 0)
{
hi = mid - 1;
}
else if (delta > 0)
{
lo = mid + 1;
}
else
{
return mid;
}
}
return hi;
}
/// <summary>
/// Gets the term at the given position. For testing.
/// </summary>
/// <param name="termIndex">
/// The position to read the term from the index. </param>
/// <returns> The term. </returns>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
internal virtual Term GetTerm(int termIndex)
{
PagedBytesDataInput input = (PagedBytesDataInput)dataInput.Clone();
input.SetPosition(indexToDataOffset.Get(termIndex));
// read the term
int fieldId = input.ReadVInt32();
Term field = fields[fieldId];
return new Term(field.Field, input.ReadString());
}
/// <summary>
/// Returns the number of terms.
/// </summary>
/// <returns> int. </returns>
internal virtual int Length => indexSize;
/// <summary>
/// The compares the given term against the term in the index specified by the
/// term index. ie It returns negative N when term is less than index term;
/// </summary>
/// <param name="term">
/// The given term. </param>
/// <param name="termIndex">
/// The index of the of term to compare. </param>
/// <returns> int. </returns>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal virtual int CompareTo(Term term, int termIndex)
{
return CompareTo(term, termIndex, (PagedBytesDataInput)dataInput.Clone(), new BytesRef());
}
/// <summary>
/// Compare the fields of the terms first, and if not equals return from
/// compare. If equal compare terms.
/// </summary>
/// <param name="term">
/// The term to compare. </param>
/// <param name="termIndex">
/// The position of the term in the input to compare </param>
/// <param name="input">
/// The input buffer. </param>
/// <returns> int. </returns>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
private int CompareTo(Term term, int termIndex, PagedBytesDataInput input, BytesRef reuse)
{
// if term field does not equal mid's field index, then compare fields
// else if they are equal, compare term's string values...
int c = CompareField(term, termIndex, input);
if (c == 0)
{
reuse.Length = input.ReadVInt32();
reuse.Grow(reuse.Length);
input.ReadBytes(reuse.Bytes, 0, reuse.Length);
return comparer.Compare(term.Bytes, reuse);
}
return c;
}
/// <summary>
/// Compares the fields before checking the text of the terms.
/// </summary>
/// <param name="term">
/// The given term. </param>
/// <param name="termIndex">
/// The term that exists in the data block. </param>
/// <param name="input">
/// The data block. </param>
/// <returns> int. </returns>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CompareField(Term term, int termIndex, PagedBytesDataInput input)
{
input.SetPosition(indexToDataOffset.Get(termIndex));
return term.Field.CompareToOrdinal(fields[input.ReadVInt32()].Field);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal virtual long RamBytesUsed()
{
return ramBytesUsed;
}
}
}