All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.pinot.segment.spi.index.IndexingOverrides Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/**
 * 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.pinot.segment.spi.index;

import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import org.apache.pinot.segment.spi.ColumnMetadata;
import org.apache.pinot.segment.spi.creator.IndexCreationContext;
import org.apache.pinot.segment.spi.creator.IndexCreatorProvider;
import org.apache.pinot.segment.spi.index.creator.BloomFilterCreator;
import org.apache.pinot.segment.spi.index.creator.CombinedInvertedIndexCreator;
import org.apache.pinot.segment.spi.index.creator.DictionaryBasedInvertedIndexCreator;
import org.apache.pinot.segment.spi.index.creator.ForwardIndexCreator;
import org.apache.pinot.segment.spi.index.creator.GeoSpatialIndexCreator;
import org.apache.pinot.segment.spi.index.creator.JsonIndexCreator;
import org.apache.pinot.segment.spi.index.creator.TextIndexCreator;
import org.apache.pinot.segment.spi.index.mutable.MutableDictionary;
import org.apache.pinot.segment.spi.index.mutable.MutableForwardIndex;
import org.apache.pinot.segment.spi.index.mutable.MutableInvertedIndex;
import org.apache.pinot.segment.spi.index.mutable.MutableJsonIndex;
import org.apache.pinot.segment.spi.index.mutable.MutableTextIndex;
import org.apache.pinot.segment.spi.index.mutable.provider.MutableIndexContext;
import org.apache.pinot.segment.spi.index.mutable.provider.MutableIndexProvider;
import org.apache.pinot.segment.spi.index.reader.BloomFilterReader;
import org.apache.pinot.segment.spi.index.reader.ForwardIndexReader;
import org.apache.pinot.segment.spi.index.reader.H3IndexReader;
import org.apache.pinot.segment.spi.index.reader.InvertedIndexReader;
import org.apache.pinot.segment.spi.index.reader.JsonIndexReader;
import org.apache.pinot.segment.spi.index.reader.RangeIndexReader;
import org.apache.pinot.segment.spi.index.reader.SortedIndexReader;
import org.apache.pinot.segment.spi.index.reader.TextIndexReader;
import org.apache.pinot.segment.spi.index.reader.provider.IndexReaderProvider;
import org.apache.pinot.segment.spi.memory.PinotDataBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class IndexingOverrides {

  public interface IndexingOverride extends IndexCreatorProvider, IndexReaderProvider, MutableIndexProvider {
  }

  private static final Logger LOGGER = LoggerFactory.getLogger(IndexingOverrides.class);

  private static final IndexCreatorProvider CREATOR_DEFAULTS = createDefaultCreatorProvider();
  private static final IndexReaderProvider READER_DEFAULTS = createDefaultReaderProvider();
  private static final MutableIndexProvider MUTABLE_INDEX_DEFAULTS = createDefaultMutableIndexProvider();

  private static final AtomicReference REGISTRATION = new AtomicReference<>(null);

  private IndexingOverrides() {
  }

  /**
   * The caller provides a decorator to wrap the default provider, which allows plugins to create
   * a delegation chain.
   * @param provider indexing override
   * @return true if this is the first invocation and the provider has not yet been used.
   */
  public static boolean registerProvider(IndexingOverride provider) {
    return REGISTRATION.compareAndSet(null, provider);
  }

  /**
   * Gets the registered {@see IndexReaderProvider} or the default if none was registered yet.
   * @return an index reader provider.
   */
  public static IndexReaderProvider getIndexReaderProvider() {
    return Holder.PROVIDER;
  }

  /**
   * Gets the registered {@see MutableIndexProvider} or the default if none was registered yet.
   * @return a mutable index reader provider.
   */
  public static MutableIndexProvider getMutableIndexProvider() {
    return Holder.PROVIDER;
  }

  /**
   * Obtain the registered index creator provider. If the user has provided an override, then it will be used instead.
   * If the user has not provided an override yet, then this action will prevent them from doing so.
   * @return the global index provision logic.
   */
  public static IndexCreatorProvider getIndexCreatorProvider() {
    return Holder.PROVIDER;
  }

  private static final class Holder {
    public static final IndexingOverride PROVIDER = Optional.ofNullable(REGISTRATION.get()).orElseGet(Default::new);
  }

  private static IndexCreatorProvider createDefaultCreatorProvider() {
    return invokeDefaultConstructor("org.apache.pinot.segment.local.segment.creator.impl.DefaultIndexCreatorProvider");
  }

  private static IndexReaderProvider createDefaultReaderProvider() {
    return invokeDefaultConstructor("org.apache.pinot.segment.local.segment.index.readers.DefaultIndexReaderProvider");
  }

  private static MutableIndexProvider createDefaultMutableIndexProvider() {
    return invokeDefaultConstructor(
        "org.apache.pinot.segment.local.indexsegment.mutable.DefaultMutableIndexProvider");
  }

  @SuppressWarnings("unchecked")
  private static  T invokeDefaultConstructor(String className) {
    try {
      Class clazz = Class.forName(className, false, IndexingOverrides.class.getClassLoader());
      return (T) MethodHandles.publicLookup()
          .findConstructor(clazz, MethodType.methodType(void.class)).invoke();
    } catch (Throwable missing) {
      LOGGER.error("could not construct MethodHandle for {}", className, missing);
      return null;
    }
  }

  /**
   * Extend this class to override index creation
   */
  public static class Default implements IndexingOverride {

    @Override
    public BloomFilterCreator newBloomFilterCreator(IndexCreationContext.BloomFilter context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newBloomFilterCreator(context);
    }

    @Override
    public ForwardIndexCreator newForwardIndexCreator(IndexCreationContext.Forward context)
        throws Exception {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newForwardIndexCreator(context);
    }

    @Override
    public GeoSpatialIndexCreator newGeoSpatialIndexCreator(IndexCreationContext.Geospatial context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newGeoSpatialIndexCreator(context);
    }

    @Override
    public DictionaryBasedInvertedIndexCreator newInvertedIndexCreator(IndexCreationContext.Inverted context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newInvertedIndexCreator(context);
    }

    @Override
    public JsonIndexCreator newJsonIndexCreator(IndexCreationContext.Json context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newJsonIndexCreator(context);
    }

    @Override
    public CombinedInvertedIndexCreator newRangeIndexCreator(IndexCreationContext.Range context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newRangeIndexCreator(context);
    }

    @Override
    public TextIndexCreator newTextIndexCreator(IndexCreationContext.Text context)
        throws IOException {
      ensureCreatorPresent();
      return CREATOR_DEFAULTS.newTextIndexCreator(context);
    }

    @Override
    public BloomFilterReader newBloomFilterReader(PinotDataBuffer dataBuffer, boolean onHeap)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newBloomFilterReader(dataBuffer, onHeap);
    }

    @Override
    public ForwardIndexReader newForwardIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newForwardIndexReader(dataBuffer, metadata);
    }

    @Override
    public H3IndexReader newGeospatialIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newGeospatialIndexReader(dataBuffer, metadata);
    }

    @Override
    public InvertedIndexReader newInvertedIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newInvertedIndexReader(dataBuffer, metadata);
    }

    @Override
    public JsonIndexReader newJsonIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newJsonIndexReader(dataBuffer, metadata);
    }

    @Override
    public RangeIndexReader newRangeIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newRangeIndexReader(dataBuffer, metadata);
    }

    @Override
    public SortedIndexReader newSortedIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newSortedIndexReader(dataBuffer, metadata);
    }

    @Override
    public TextIndexReader newFSTIndexReader(PinotDataBuffer dataBuffer, ColumnMetadata metadata)
        throws IOException {
      ensureReaderPresent();
      return READER_DEFAULTS.newFSTIndexReader(dataBuffer, metadata);
    }

    @Override
    public TextIndexReader newTextIndexReader(File file, ColumnMetadata columnMetadata,
        @Nullable Map textIndexProperties) {
      ensureReaderPresent();
      return READER_DEFAULTS.newTextIndexReader(file, columnMetadata, textIndexProperties);
    }

    @Override
    public MutableForwardIndex newForwardIndex(MutableIndexContext.Forward context) {
      ensureMutableReaderPresent();
      return MUTABLE_INDEX_DEFAULTS.newForwardIndex(context);
    }

    @Override
    public MutableInvertedIndex newInvertedIndex(MutableIndexContext.Inverted context) {
      ensureMutableReaderPresent();
      return MUTABLE_INDEX_DEFAULTS.newInvertedIndex(context);
    }

    @Override
    public MutableTextIndex newTextIndex(MutableIndexContext.Text context) {
      ensureMutableReaderPresent();
      return MUTABLE_INDEX_DEFAULTS.newTextIndex(context);
    }

    @Override
    public MutableJsonIndex newJsonIndex(MutableIndexContext.Json context) {
      ensureMutableReaderPresent();
      return MUTABLE_INDEX_DEFAULTS.newJsonIndex(context);
    }

    @Override
    public MutableDictionary newDictionary(MutableIndexContext.Dictionary context) {
      ensureMutableReaderPresent();
      return MUTABLE_INDEX_DEFAULTS.newDictionary(context);
    }

    private void ensureReaderPresent() {
      if (READER_DEFAULTS == null) {
        throw new UnsupportedOperationException("default implementation not present on classpath");
      }
    }

    private void ensureMutableReaderPresent() {
      if (MUTABLE_INDEX_DEFAULTS == null) {
        throw new UnsupportedOperationException("default implementation not present on classpath");
      }
    }

    private void ensureCreatorPresent() {
      if (CREATOR_DEFAULTS == null) {
        throw new UnsupportedOperationException("default implementation not present on classpath");
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy