/**
   * If there are configured {@link IndexSearcherWrapper} instances, the {@link IndexSearcher} of
   * the provided engine searcher gets wrapped and a new {@link Engine.Searcher} instances is
   * returned, otherwise the provided {@link Engine.Searcher} is returned.
   *
   * <p>This is invoked each time a {@link Engine.Searcher} is requested to do an operation. (for
   * example search)
   */
  public final Engine.Searcher wrap(EngineConfig engineConfig, Engine.Searcher engineSearcher)
      throws IOException {
    final ElasticsearchDirectoryReader elasticsearchDirectoryReader =
        ElasticsearchDirectoryReader.getElasticsearchDirectoryReader(
            engineSearcher.getDirectoryReader());
    if (elasticsearchDirectoryReader == null) {
      throw new IllegalStateException("Can't wrap non elasticsearch directory reader");
    }
    NonClosingReaderWrapper nonClosingReaderWrapper =
        new NonClosingReaderWrapper(engineSearcher.getDirectoryReader());
    DirectoryReader reader = wrap(nonClosingReaderWrapper);
    if (reader != nonClosingReaderWrapper) {
      if (reader.getCoreCacheKey() != elasticsearchDirectoryReader.getCoreCacheKey()) {
        throw new IllegalStateException(
            "wrapped directory reader doesn't delegate IndexReader#getCoreCacheKey, wrappers must override this method and delegate"
                + " to the original readers core cache key. Wrapped readers can't be used as cache keys since their are used only per request which would lead to subtle bugs");
      }
      if (ElasticsearchDirectoryReader.getElasticsearchDirectoryReader(reader)
          != elasticsearchDirectoryReader) {
        // prevent that somebody wraps with a non-filter reader
        throw new IllegalStateException(
            "wrapped directory reader hides actual ElasticsearchDirectoryReader but shouldn't");
      }
    }

    final IndexSearcher innerIndexSearcher = new IndexSearcher(reader);
    innerIndexSearcher.setQueryCache(engineConfig.getQueryCache());
    innerIndexSearcher.setQueryCachingPolicy(engineConfig.getQueryCachingPolicy());
    innerIndexSearcher.setSimilarity(engineConfig.getSimilarity());
    // TODO: Right now IndexSearcher isn't wrapper friendly, when it becomes wrapper friendly we
    // should revise this extension point
    // For example if IndexSearcher#rewrite() is overwritten than also
    // IndexSearcher#createNormalizedWeight needs to be overwritten
    // This needs to be fixed before we can allow the IndexSearcher from Engine to be wrapped
    // multiple times
    final IndexSearcher indexSearcher = wrap(engineConfig, innerIndexSearcher);
    if (reader == nonClosingReaderWrapper && indexSearcher == innerIndexSearcher) {
      return engineSearcher;
    } else {
      return new Engine.Searcher(engineSearcher.source(), indexSearcher) {
        @Override
        public void close() throws ElasticsearchException {
          try {
            reader().close();
            // we close the reader to make sure wrappers can release resources if needed....
            // our NonClosingReaderWrapper makes sure that our reader is not closed
          } catch (IOException e) {
            throw new ElasticsearchException("failed to close reader", e);
          } finally {
            engineSearcher.close();
          }
        }
      };
    }
  }
Пример #2
0
    @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();
    }
Пример #3
0
 public DirectoryReader getDirectoryReader() {
   return engineSearcher.getDirectoryReader();
 }