private synchronized void handleDVUpdates()

in lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java [283:448]


  private synchronized void handleDVUpdates(
      FieldInfos infos,
      Directory dir,
      DocValuesFormat dvFormat,
      final SegmentReader reader,
      Map<Integer, Set<String>> fieldFiles,
      long maxDelGen,
      InfoStream infoStream)
      throws IOException {
    for (Entry<String, List<DocValuesFieldUpdates>> ent : pendingDVUpdates.entrySet()) {
      final String field = ent.getKey();
      final List<DocValuesFieldUpdates> updates = ent.getValue();
      DocValuesType type = updates.get(0).type;
      assert type == DocValuesType.NUMERIC || type == DocValuesType.BINARY
          : "unsupported type: " + type;
      final List<DocValuesFieldUpdates> updatesToApply = new ArrayList<>();
      long bytes = 0;
      for (DocValuesFieldUpdates update : updates) {
        if (update.delGen <= maxDelGen) {
          // safe to apply this one
          bytes += update.ramBytesUsed();
          updatesToApply.add(update);
        }
      }
      if (updatesToApply.isEmpty()) {
        // nothing to apply yet
        continue;
      }
      if (infoStream.isEnabled("BD")) {
        infoStream.message(
            "BD",
            String.format(
                Locale.ROOT,
                "now write %d pending numeric DV updates for field=%s, seg=%s, bytes=%.3f MB",
                updatesToApply.size(),
                field,
                info,
                bytes / 1024. / 1024.));
      }
      final long nextDocValuesGen = info.getNextDocValuesGen();
      final String segmentSuffix = Long.toString(nextDocValuesGen, Character.MAX_RADIX);
      final IOContext updatesContext = IOContext.flush(new FlushInfo(info.info.maxDoc(), bytes));
      final FieldInfo fieldInfo = infos.fieldInfo(field);
      assert fieldInfo != null;
      fieldInfo.setDocValuesGen(nextDocValuesGen);
      final FieldInfos fieldInfos = new FieldInfos(new FieldInfo[] {fieldInfo});
      // separately also track which files were created for this gen
      final TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(dir);
      final SegmentWriteState state =
          new SegmentWriteState(
              null, trackingDir, info.info, fieldInfos, null, updatesContext, segmentSuffix);
      try (final DocValuesConsumer fieldsConsumer = dvFormat.fieldsConsumer(state)) {
        Function<FieldInfo, DocValuesFieldUpdates.Iterator> updateSupplier =
            (info) -> {
              if (info != fieldInfo) {
                throw new IllegalArgumentException(
                    "expected field info for field: " + fieldInfo.name + " but got: " + info.name);
              }
              DocValuesFieldUpdates.Iterator[] subs =
                  new DocValuesFieldUpdates.Iterator[updatesToApply.size()];
              for (int i = 0; i < subs.length; i++) {
                subs[i] = updatesToApply.get(i).iterator();
              }
              return DocValuesFieldUpdates.mergedIterator(subs);
            };
        pendingDeletes.onDocValuesUpdate(fieldInfo, updateSupplier.apply(fieldInfo));
        if (type == DocValuesType.BINARY) {
          fieldsConsumer.addBinaryField(
              fieldInfo,
              new EmptyDocValuesProducer() {
                @Override
                public BinaryDocValues getBinary(FieldInfo fieldInfoIn) throws IOException {
                  DocValuesFieldUpdates.Iterator iterator = updateSupplier.apply(fieldInfo);
                  final MergedDocValues<BinaryDocValues> mergedDocValues =
                      new MergedDocValues<>(
                          reader.getBinaryDocValues(field),
                          DocValuesFieldUpdates.Iterator.asBinaryDocValues(iterator),
                          iterator);
                  // Merge sort of the original doc values with updated doc values:
                  return new BinaryDocValues() {
                    @Override
                    public BytesRef binaryValue() throws IOException {
                      return mergedDocValues.currentValuesSupplier.binaryValue();
                    }

                    @Override
                    public boolean advanceExact(int target) {
                      return mergedDocValues.advanceExact(target);
                    }

                    @Override
                    public int docID() {
                      return mergedDocValues.docID();
                    }

                    @Override
                    public int nextDoc() throws IOException {
                      return mergedDocValues.nextDoc();
                    }

                    @Override
                    public int advance(int target) {
                      return mergedDocValues.advance(target);
                    }

                    @Override
                    public long cost() {
                      return mergedDocValues.cost();
                    }
                  };
                }
              });
        } else {
          // write the numeric updates to a new gen'd docvalues file
          fieldsConsumer.addNumericField(
              fieldInfo,
              new EmptyDocValuesProducer() {
                @Override
                public NumericDocValues getNumeric(FieldInfo fieldInfoIn) throws IOException {
                  DocValuesFieldUpdates.Iterator iterator = updateSupplier.apply(fieldInfo);
                  final MergedDocValues<NumericDocValues> mergedDocValues =
                      new MergedDocValues<>(
                          reader.getNumericDocValues(field),
                          DocValuesFieldUpdates.Iterator.asNumericDocValues(iterator),
                          iterator);
                  // Merge sort of the original doc values with updated doc values:
                  return new NumericDocValues() {
                    @Override
                    public long longValue() throws IOException {
                      return mergedDocValues.currentValuesSupplier.longValue();
                    }

                    @Override
                    public boolean advanceExact(int target) {
                      return mergedDocValues.advanceExact(target);
                    }

                    @Override
                    public int docID() {
                      return mergedDocValues.docID();
                    }

                    @Override
                    public int nextDoc() throws IOException {
                      return mergedDocValues.nextDoc();
                    }

                    @Override
                    public int advance(int target) {
                      return mergedDocValues.advance(target);
                    }

                    @Override
                    public long cost() {
                      return mergedDocValues.cost();
                    }
                  };
                }
              });
        }
      }
      info.advanceDocValuesGen();
      assert !fieldFiles.containsKey(fieldInfo.number);
      fieldFiles.put(fieldInfo.number, trackingDir.getCreatedFiles());
    }
  }