jimczi commented on code in PR #16769:
URL: https://github.com/apache/lucene/pull/16769#discussion_r4205760219


##########
lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99FlatVectorsReader.java:
##########
@@ -218,42 +224,55 @@ public FlatVectorsReader getMergeInstance() throws 
IOException {
       return mergeInstance;
     } finally {
       if (success == false) {
-        original.releaseMergeVectorData();
+        original.release();
       }
     }
   }
 
+  /**
+   * Whether a merge has to map the file again: only when searches read it at 
random. Otherwise the
+   * mapping searches use carries no advice a merge reading front to back 
would suffer from, and a
+   * reader a merge opened already reads the file the way a merge does.
+   */
+  private boolean mergeNeedsItsOwnMapping() {
+    return dataContext.context() != IOContext.Context.MERGE
+        && dataContext.hints().contains(DataAccessHint.RANDOM);

Review Comment:
   Agreed, I updated the #16749 entry to say a merge maps the vectors again 
only when searches read them at random, and the #16769 entry now only covers 
what this PR adds.



##########
lucene/sandbox/src/java/org/apache/lucene/sandbox/codecs/dedup/MergeInput.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.sandbox.codecs.dedup;
+
+import java.io.Closeable;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import java.util.stream.Stream;
+import org.apache.lucene.store.DataAccessHint;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+import org.apache.lucene.store.IndexInput;
+import org.apache.lucene.store.NoReuseHint;
+
+/**
+ * The raw vectors as merges read them: at random, since a duplicate reads its 
group's vector back,
+ * and not reused. Read advice applies to a whole mapping, so when searches 
read the file
+ * differently a merge maps it again instead of reading through the mapping 
searches use.
+ *
+ * <p>The mapping is opened when a merge first asks for it, shared by the 
merges that follow, and
+ * closed when the last one is done, or with the reader.
+ */
+final class MergeInput implements Closeable {
+  private final Directory directory;
+  private final String fileName;
+  private final IOContext context;
+  private final IndexInput searchInput;
+  private IndexInput mergeInput;
+  // merges holding the mapping and not yet finished
+  private int merges;
+
+  /**
+   * @param context the context {@code searchInput} was opened with
+   */
+  MergeInput(Directory directory, String fileName, IOContext context, 
IndexInput searchInput) {
+    this.directory = directory;
+    this.fileName = fileName;
+    this.context = context;
+    this.searchInput = searchInput;
+  }
+
+  /**
+   * Whether a merge needs a mapping of its own: only when searches read the 
file differently. A
+   * file a merge opened is already read the way a merge reads it.
+   */
+  boolean needed() {
+    return context.context() != IOContext.Context.MERGE
+        && context.hints().equals(mergeContext().hints()) == false;
+  }
+
+  /** The mapping for one more merge, to give back with {@link #release()}. */
+  synchronized IndexInput acquire() throws IOException {
+    assert needed();
+    if (mergeInput == null) {
+      try {
+        mergeInput = directory.openInput(fileName, mergeContext());
+      } catch (FileNotFoundException | NoSuchFileException _) {
+        // an open reader outlives its files, so fall back to the mapping it 
already holds
+        mergeInput = searchInput;
+      }
+    }
+    merges++;
+    return mergeInput;
+  }
+
+  /** Gives back the mapping of a merge that is done, closing it after the 
last one. */
+  synchronized void release() throws IOException {
+    assert merges > 0;
+    if (--merges > 0) {
+      return;
+    }
+    if (mergeInput != null && mergeInput != searchInput) {
+      mergeInput.close();

Review Comment:
   Good catch. `MergeInput` is gone with the de-duplicating formats, but 
`Lucene99FlatVectorsReader` had the same pattern: the last merge instance now 
takes the mapping under the lock and closes it outside.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to