30
30
import org .apache .lucene .store .IndexInput ;
31
31
import org .apache .lucene .util .Bits ;
32
32
import org .elasticsearch .core .IOUtils ;
33
+ import org .elasticsearch .index .codec .vectors .GenericFlatVectorReaders ;
33
34
import org .elasticsearch .search .vectors .IVFKnnSearchStrategy ;
34
35
35
36
import java .io .Closeable ;
36
37
import java .io .IOException ;
37
38
import java .util .ArrayList ;
38
39
import java .util .Collections ;
39
- import java .util .HashMap ;
40
40
import java .util .List ;
41
41
import java .util .Map ;
42
42
49
49
*/
50
50
public abstract class IVFVectorsReader extends KnnVectorsReader {
51
51
52
- private record FlatVectorsReaderKey (String formatName , boolean useDirectIO ) {
53
- private FlatVectorsReaderKey (FieldEntry entry ) {
54
- this (entry .rawVectorFormatName , entry .useDirectIOReads );
55
- }
56
-
57
- @ Override
58
- public String toString () {
59
- return formatName + (useDirectIO ? " with Direct IO" : "" );
60
- }
61
- }
62
-
63
52
private final IndexInput ivfCentroids , ivfClusters ;
64
53
private final SegmentReadState state ;
65
54
private final FieldInfos fieldInfos ;
66
55
protected final IntObjectHashMap <FieldEntry > fields ;
67
- private final Map <FlatVectorsReaderKey , FlatVectorsReader > rawVectorReaders ;
68
-
69
- @ FunctionalInterface
70
- public interface GetFormatReader {
71
- FlatVectorsReader getReader (String formatName , boolean useDirectIO ) throws IOException ;
72
- }
56
+ private final GenericFlatVectorReaders genericReaders ;
73
57
74
58
@ SuppressWarnings ("this-escape" )
75
- protected IVFVectorsReader (SegmentReadState state , GetFormatReader getFormatReader ) throws IOException {
59
+ protected IVFVectorsReader (SegmentReadState state , GenericFlatVectorReaders . LoadFlatVectorsReader loadReader ) throws IOException {
76
60
this .state = state ;
77
61
this .fieldInfos = state .fieldInfos ;
78
62
this .fields = new IntObjectHashMap <>();
63
+ this .genericReaders = new GenericFlatVectorReaders ();
79
64
String meta = IndexFileNames .segmentFileName (
80
65
state .segmentInfo .name ,
81
66
state .segmentSuffix ,
@@ -86,7 +71,6 @@ protected IVFVectorsReader(SegmentReadState state, GetFormatReader getFormatRead
86
71
boolean success = false ;
87
72
try (ChecksumIndexInput ivfMeta = state .directory .openChecksumInput (meta )) {
88
73
Throwable priorE = null ;
89
- Map <FlatVectorsReaderKey , FlatVectorsReader > readers = null ;
90
74
try {
91
75
versionMeta = CodecUtil .checkIndexHeader (
92
76
ivfMeta ,
@@ -96,13 +80,12 @@ protected IVFVectorsReader(SegmentReadState state, GetFormatReader getFormatRead
96
80
state .segmentInfo .getId (),
97
81
state .segmentSuffix
98
82
);
99
- readers = readFields (ivfMeta , getFormatReader , versionMeta );
83
+ readFields (ivfMeta , versionMeta , genericReaders , loadReader );
100
84
} catch (Throwable exception ) {
101
85
priorE = exception ;
102
86
} finally {
103
87
CodecUtil .checkFooter (ivfMeta , priorE );
104
88
}
105
- this .rawVectorReaders = readers ;
106
89
ivfCentroids = openDataInput (
107
90
state ,
108
91
versionMeta ,
@@ -169,30 +152,23 @@ private static IndexInput openDataInput(
169
152
}
170
153
}
171
154
172
- private Map <FlatVectorsReaderKey , FlatVectorsReader > readFields (ChecksumIndexInput meta , GetFormatReader loadReader , int versionMeta )
173
- throws IOException {
174
- Map <FlatVectorsReaderKey , FlatVectorsReader > readers = new HashMap <>();
155
+ private void readFields (
156
+ ChecksumIndexInput meta ,
157
+ int versionMeta ,
158
+ GenericFlatVectorReaders genericFields ,
159
+ GenericFlatVectorReaders .LoadFlatVectorsReader loadReader
160
+ ) throws IOException {
175
161
for (int fieldNumber = meta .readInt (); fieldNumber != -1 ; fieldNumber = meta .readInt ()) {
176
162
final FieldInfo info = fieldInfos .fieldInfo (fieldNumber );
177
163
if (info == null ) {
178
164
throw new CorruptIndexException ("Invalid field number: " + fieldNumber , meta );
179
165
}
180
166
181
167
FieldEntry fieldEntry = readField (meta , info , versionMeta );
182
- FlatVectorsReaderKey key = new FlatVectorsReaderKey (fieldEntry );
183
-
184
- FlatVectorsReader reader = readers .get (key );
185
- if (reader == null ) {
186
- reader = loadReader .getReader (fieldEntry .rawVectorFormatName , fieldEntry .useDirectIOReads );
187
- if (reader == null ) {
188
- throw new IllegalStateException ("Cannot find flat vector format: " + fieldEntry .rawVectorFormatName );
189
- }
190
- readers .put (key , reader );
191
- }
168
+ genericFields .loadField (fieldNumber , fieldEntry , loadReader );
192
169
193
170
fields .put (info .number , fieldEntry );
194
171
}
195
- return readers ;
196
172
}
197
173
198
174
private FieldEntry readField (IndexInput input , FieldInfo info , int versionMeta ) throws IOException {
@@ -256,29 +232,17 @@ private static VectorEncoding readVectorEncoding(DataInput input) throws IOExcep
256
232
257
233
@ Override
258
234
public final void checkIntegrity () throws IOException {
259
- for (var reader : rawVectorReaders . values ()) {
235
+ for (var reader : genericReaders . allReaders ()) {
260
236
reader .checkIntegrity ();
261
237
}
262
238
CodecUtil .checksumEntireFile (ivfCentroids );
263
239
CodecUtil .checksumEntireFile (ivfClusters );
264
240
}
265
241
266
- private FieldEntry getFieldEntryOrThrow (String field ) {
267
- final FieldInfo info = fieldInfos .fieldInfo (field );
268
- final FieldEntry entry ;
269
- if (info == null || (entry = fields .get (info .number )) == null ) {
270
- throw new IllegalArgumentException ("field=\" " + field + "\" not found" );
271
- }
272
- return entry ;
273
- }
274
-
275
242
private FlatVectorsReader getReaderForField (String field ) {
276
- var readerKey = new FlatVectorsReaderKey (getFieldEntryOrThrow (field ));
277
- FlatVectorsReader reader = rawVectorReaders .get (readerKey );
278
- if (reader == null ) throw new IllegalArgumentException (
279
- "Could not find raw vector format [" + readerKey + "] for field [" + field + "]"
280
- );
281
- return reader ;
243
+ FieldInfo info = fieldInfos .fieldInfo (field );
244
+ if (info == null ) throw new IllegalArgumentException ("Could not find field [" + field + "]" );
245
+ return genericReaders .getReaderForField (info .number );
282
246
}
283
247
284
248
@ Override
@@ -399,7 +363,7 @@ public Map<String, Long> getOffHeapByteSize(FieldInfo fieldInfo) {
399
363
400
364
@ Override
401
365
public void close () throws IOException {
402
- List <Closeable > closeables = new ArrayList <>(rawVectorReaders . values ());
366
+ List <Closeable > closeables = new ArrayList <>(genericReaders . allReaders ());
403
367
Collections .addAll (closeables , ivfCentroids , ivfClusters );
404
368
IOUtils .close (closeables );
405
369
}
@@ -416,7 +380,7 @@ protected record FieldEntry(
416
380
long postingListLength ,
417
381
float [] globalCentroid ,
418
382
float globalCentroidDp
419
- ) {
383
+ ) implements GenericFlatVectorReaders . Field {
420
384
IndexInput centroidSlice (IndexInput centroidFile ) throws IOException {
421
385
return centroidFile .slice ("centroids" , centroidOffset , centroidLength );
422
386
}
0 commit comments