@Override
    public TerminationHandle warmReader(
        final IndexShard indexShard, final Engine.Searcher searcher) {
      final MapperService mapperService = indexShard.mapperService();
      final Map<String, MappedFieldType> warmUpGlobalOrdinals = new HashMap<>();
      for (DocumentMapper docMapper : mapperService.docMappers(false)) {
        for (FieldMapper fieldMapper : docMapper.mappers()) {
          final MappedFieldType fieldType = fieldMapper.fieldType();
          final String indexName = fieldType.name();
          if (fieldType.eagerGlobalOrdinals() == false) {
            continue;
          }
          warmUpGlobalOrdinals.put(indexName, fieldType);
        }
      }
      final IndexFieldDataService indexFieldDataService = indexShard.indexFieldDataService();
      final CountDownLatch latch = new CountDownLatch(warmUpGlobalOrdinals.size());
      for (final MappedFieldType fieldType : warmUpGlobalOrdinals.values()) {
        executor.execute(
            () -> {
              try {
                final long start = System.nanoTime();
                IndexFieldData.Global ifd = indexFieldDataService.getForField(fieldType);
                DirectoryReader reader = searcher.getDirectoryReader();
                IndexFieldData<?> global = ifd.loadGlobal(reader);
                if (reader.leaves().isEmpty() == false) {
                  global.load(reader.leaves().get(0));
                }

                if (indexShard.warmerService().logger().isTraceEnabled()) {
                  indexShard
                      .warmerService()
                      .logger()
                      .trace(
                          "warmed global ordinals for [{}], took [{}]",
                          fieldType.name(),
                          TimeValue.timeValueNanos(System.nanoTime() - start));
                }
              } catch (Exception e) {
                indexShard
                    .warmerService()
                    .logger()
                    .warn("failed to warm-up global ordinals for [{}]", e, fieldType.name());
              } finally {
                latch.countDown();
              }
            });
      }
      return () -> latch.await();
    }
 void warm(Engine.Searcher searcher, IndexShard shard, IndexSettings settings) {
   if (shard.state() == IndexShardState.CLOSED) {
     return;
   }
   if (settings.isWarmerEnabled() == false) {
     return;
   }
   if (logger.isTraceEnabled()) {
     logger.trace("{} top warming [{}]", shard.shardId(), searcher.reader());
   }
   shard.warmerService().onPreWarm();
   long time = System.nanoTime();
   final List<TerminationHandle> terminationHandles = new ArrayList<>();
   // get a handle on pending tasks
   for (final Listener listener : listeners) {
     terminationHandles.add(listener.warmReader(shard, searcher));
   }
   // wait for termination
   for (TerminationHandle terminationHandle : terminationHandles) {
     try {
       terminationHandle.awaitTermination();
     } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
       logger.warn("top warming has been interrupted", e);
       break;
     }
   }
   long took = System.nanoTime() - time;
   shard.warmerService().onPostWarm(took);
   if (shard.warmerService().logger().isTraceEnabled()) {
     shard
         .warmerService()
         .logger()
         .trace("top warming took [{}]", new TimeValue(took, TimeUnit.NANOSECONDS));
   }
 }