forked from apache/lucenenet
-
Notifications
You must be signed in to change notification settings - Fork 3
/
BaseCompositeReader.cs
235 lines (217 loc) · 8.85 KB
/
BaseCompositeReader.cs
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
using J2N.Collections.Generic.Extensions;
using System;
using System.Collections.Generic;
using JCG = J2N.Collections.Generic;
namespace Lucene.Net.Index
{
/*
* 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.
*/
/// <summary>
/// Base class for implementing <see cref="CompositeReader"/>s based on an array
/// of sub-readers. The implementing class has to add code for
/// correctly refcounting and closing the sub-readers.
///
/// <para/>User code will most likely use <see cref="MultiReader"/> to build a
/// composite reader on a set of sub-readers (like several
/// <see cref="DirectoryReader"/>s).
///
/// <para/> For efficiency, in this API documents are often referred to via
/// <i>document numbers</i>, non-negative integers which each name a unique
/// document in the index. These document numbers are ephemeral -- they may change
/// as documents are added to and deleted from an index. Clients should thus not
/// rely on a given document having the same number between sessions.
///
/// <para/><b>NOTE</b>:
/// <see cref="IndexReader"/> instances are completely thread
/// safe, meaning multiple threads can call any of its methods,
/// concurrently. If your application requires external
/// synchronization, you should <b>not</b> synchronize on the
/// <see cref="IndexReader"/> instance; use your own
/// (non-Lucene) objects instead.
/// <para/>
/// @lucene.internal
/// </summary>
/// <seealso cref="MultiReader"/>
public abstract class BaseCompositeReader<R> : CompositeReader
where R : IndexReader
{
private readonly R[] subReaders;
private readonly int[] starts; // 1st docno for each reader
private readonly int maxDoc;
private readonly int numDocs;
/// <summary>
/// List view solely for <see cref="GetSequentialSubReaders()"/>,
/// for effectiveness the array is used internally.
/// </summary>
private readonly IList<IndexReader> subReadersList; // LUCENENET: Changed from IList<R> to IList<IndexReader> to eliminate casting
/// <summary>
/// Constructs a <see cref="BaseCompositeReader{R}"/> on the given <paramref name="subReaders"/>. </summary>
/// <param name="subReaders"> the wrapped sub-readers. This array is returned by
/// <see cref="GetSequentialSubReaders()"/> and used to resolve the correct
/// subreader for docID-based methods. <b>Please note:</b> this array is <b>not</b>
/// cloned and not protected for modification, the subclass is responsible
/// to do this. </param>
protected BaseCompositeReader(R[] subReaders)
{
this.subReaders = subReaders;
// LUCENENET: To eliminate casting, we create the list explicitly
var subReadersList = new JCG.List<IndexReader>(subReaders.Length);
for (int i = 0; i < subReaders.Length; i++)
subReadersList.Add(subReaders[i]);
this.subReadersList = subReadersList.AsReadOnly();
starts = new int[subReaders.Length + 1]; // build starts array
int maxDoc = 0, numDocs = 0;
for (int i = 0; i < subReaders.Length; i++)
{
starts[i] = maxDoc;
IndexReader r = subReaders[i];
maxDoc += r.MaxDoc; // compute maxDocs
if (maxDoc < 0) // overflow
{
throw new ArgumentException("Too many documents, composite IndexReaders cannot exceed " + int.MaxValue);
}
numDocs += r.NumDocs; // compute numDocs
r.RegisterParentReader(this);
}
starts[subReaders.Length] = maxDoc;
this.maxDoc = maxDoc;
this.numDocs = numDocs;
}
public override sealed Fields GetTermVectors(int docID)
{
EnsureOpen();
int i = ReaderIndex(docID); // find subreader num
return subReaders[i].GetTermVectors(docID - starts[i]); // dispatch to subreader
}
public override sealed int NumDocs
{
get
{
// Don't call ensureOpen() here (it could affect performance)
return numDocs;
}
}
public override sealed int MaxDoc
{
get
{
// Don't call ensureOpen() here (it could affect performance)
return maxDoc;
}
}
public override sealed void Document(int docID, StoredFieldVisitor visitor)
{
EnsureOpen();
int i = ReaderIndex(docID); // find subreader num
subReaders[i].Document(docID - starts[i], visitor); // dispatch to subreader
}
public override sealed int DocFreq(Term term)
{
EnsureOpen();
int total = 0; // sum freqs in subreaders
for (int i = 0; i < subReaders.Length; i++)
{
total += subReaders[i].DocFreq(term);
}
return total;
}
public override sealed long TotalTermFreq(Term term)
{
EnsureOpen();
long total = 0; // sum freqs in subreaders
for (int i = 0; i < subReaders.Length; i++)
{
long sub = subReaders[i].TotalTermFreq(term);
if (sub == -1)
{
return -1;
}
total += sub;
}
return total;
}
public override sealed long GetSumDocFreq(string field)
{
EnsureOpen();
long total = 0; // sum doc freqs in subreaders
foreach (R reader in subReaders)
{
long sub = reader.GetSumDocFreq(field);
if (sub == -1)
{
return -1; // if any of the subs doesn't support it, return -1
}
total += sub;
}
return total;
}
public override sealed int GetDocCount(string field)
{
EnsureOpen();
int total = 0; // sum doc counts in subreaders
foreach (R reader in subReaders)
{
int sub = reader.GetDocCount(field);
if (sub == -1)
{
return -1; // if any of the subs doesn't support it, return -1
}
total += sub;
}
return total;
}
public override sealed long GetSumTotalTermFreq(string field)
{
EnsureOpen();
long total = 0; // sum doc total term freqs in subreaders
foreach (R reader in subReaders)
{
long sub = reader.GetSumTotalTermFreq(field);
if (sub == -1)
{
return -1; // if any of the subs doesn't support it, return -1
}
total += sub;
}
return total;
}
/// <summary>
/// Helper method for subclasses to get the corresponding reader for a doc ID </summary>
protected internal int ReaderIndex(int docID)
{
if (docID < 0 || docID >= maxDoc)
{
throw new System.ArgumentException("docID must be >= 0 and < maxDoc=" + maxDoc + " (got docID=" + docID + ")");
}
return ReaderUtil.SubIndex(docID, this.starts);
}
/// <summary>
/// Helper method for subclasses to get the docBase of the given sub-reader index. </summary>
protected internal int ReaderBase(int readerIndex)
{
if (readerIndex < 0 || readerIndex >= subReaders.Length)
{
throw new System.ArgumentException("readerIndex must be >= 0 and < getSequentialSubReaders().size()");
}
return this.starts[readerIndex];
}
protected internal override sealed IList<IndexReader> GetSequentialSubReaders()
{
return subReadersList;
}
}
}