@Override
 protected final void writerSegmentStats(SegmentsStats stats) {
   stats.addVersionMapMemoryInBytes(versionMap.ramBytesUsed());
   stats.addIndexWriterMemoryInBytes(indexWriter.ramBytesUsed());
   stats.addIndexWriterMaxMemoryInBytes(
       (long) (indexWriter.getConfig().getRAMBufferSizeMB() * 1024 * 1024));
 }
  @Override
  public void writeIndexingBuffer() throws EngineException {

    // we obtain a read lock here, since we don't want a flush to happen while we are writing
    // since it flushes the index as well (though, in terms of concurrency, we are allowed to do it)
    try (ReleasableLock lock = readLock.acquire()) {
      ensureOpen();

      // TODO: it's not great that we secretly tie searcher visibility to "freeing up heap" here...
      // really we should keep two
      // searcher managers, one for searching which is only refreshed by the schedule the user
      // requested (refresh_interval, or invoking
      // refresh API), and another for version map interactions.  See #15768.
      final long versionMapBytes = versionMap.ramBytesUsedForRefresh();
      final long indexingBufferBytes = indexWriter.ramBytesUsed();

      final boolean useRefresh =
          versionMapRefreshPending.get() || (indexingBufferBytes / 4 < versionMapBytes);
      if (useRefresh) {
        // The version map is using > 25% of the indexing buffer, so we do a refresh so the version
        // map also clears
        logger.debug(
            "use refresh to write indexing buffer (heap size=[{}]), to also clear version map (heap size=[{}])",
            new ByteSizeValue(indexingBufferBytes),
            new ByteSizeValue(versionMapBytes));
        refresh("write indexing buffer");
      } else {
        // Most of our heap is used by the indexing buffer, so we do a cheaper (just writes
        // segments, doesn't open a new searcher) IW.flush:
        logger.debug(
            "use IndexWriter.flush to write indexing buffer (heap size=[{}]) since version map is small (heap size=[{}])",
            new ByteSizeValue(indexingBufferBytes),
            new ByteSizeValue(versionMapBytes));
        indexWriter.flush();
      }
    } catch (AlreadyClosedException e) {
      ensureOpen();
      maybeFailEngine("writeIndexingBuffer", e);
    } catch (EngineClosedException e) {
      throw e;
    } catch (Throwable t) {
      failEngine("writeIndexingBuffer failed", t);
      throw new RefreshFailedEngineException(shardId, t);
    }
  }
 @Override
 public long getIndexBufferRAMBytesUsed() {
   return indexWriter.ramBytesUsed() + versionMap.ramBytesUsedForRefresh();
 }