class GridIndexingManager extends GridManagerAdapter<IndexingSpi> {
    /** */
    private final GridSpinBusyLock busyLock = new GridSpinBusyLock();

    /**
     * @param ctx  Kernal context.
     */
    public GridIndexingManager(GridKernalContext ctx) {
        super(ctx, ctx.config().getIndexingSpi());
    }

    /**
     * @throws IgniteCheckedException Thrown in case of any errors.
     */
    @Override public void start() throws IgniteCheckedException {
        startSpi();

        if (log.isDebugEnabled())
            log.debug(startInfo());
    }

    /** {@inheritDoc} */
    @Override protected void onKernalStop0(boolean cancel) {
        busyLock.block();
    }

    /**
     * @throws IgniteCheckedException Thrown in case of any errors.
     */
    @Override public void stop(boolean cancel) throws IgniteCheckedException {
        stopSpi();

        if (log.isDebugEnabled())
            log.debug(stopInfo());
    }

    /**
     * Writes key-value pair to index.
     *
     * @param cacheName Cache name.
     * @param key Key.
     * @param val Value.
     * @param expirationTime Expiration time or 0 if never expires.
     * @throws IgniteCheckedException In case of error.
     */
    public <K, V> void store(final String cacheName, final K key, final V val, long expirationTime)
        throws IgniteCheckedException {
        assert key != null;
        assert val != null;
        assert enabled();

        if (!busyLock.enterBusy())
            throw new IllegalStateException("Failed to write to index (grid is stopping).");

        try {
            if (log.isDebugEnabled())
                log.debug("Storing key to cache query index [key=" + key + ", value=" + val + "]");

            getSpi().store(cacheName, key, val, expirationTime);
        }
        finally {
            busyLock.leaveBusy();
        }
    }

    /**
     * @param cacheName Cache name.
     * @param key Key.
     * @throws IgniteCheckedException Thrown in case of any errors.
     */
    public void remove(String cacheName, Object key) throws IgniteCheckedException {
        assert key != null;
        assert enabled();

        if (!busyLock.enterBusy())
            throw new IllegalStateException("Failed to remove from index (grid is stopping).");

        try {
            getSpi().remove(cacheName, key);
        }
        finally {
            busyLock.leaveBusy();
        }
    }

    /**
     * @param cacheName Cache name.
     * @param params Parameters collection.
     * @param filters Filters.
     * @return Query result.
     * @throws IgniteCheckedException If failed.
     */
    public IgniteSpiCloseableIterator<?> query(String cacheName, Collection<Object> params, IndexingQueryFilter filters)
        throws IgniteCheckedException {<FILL_FUNCTION_BODY>}
}

        if (!enabled())
            throw new IgniteCheckedException("Indexing SPI is not configured.");

        if (!busyLock.enterBusy())
            throw new IllegalStateException("Failed to execute query (grid is stopping).");

        try {
            final Iterator<?> res = getSpi().query(cacheName, params, filters);

            if (res == null)
                return new GridEmptyCloseableIterator<>();

            return new IgniteSpiCloseableIterator<Object>() {
                @Override public void close() throws IgniteCheckedException {
                    if (res instanceof AutoCloseable) {
                        try {
                            ((AutoCloseable)res).close();
                        }
                        catch (Exception e) {
                            throw new IgniteCheckedException(e);
                        }
                    }
                }

                @Override public boolean hasNext() {
                    return res.hasNext();
                }

                @Override public Object next() {
                    return res.next();
                }

                @Override public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
        finally {
            busyLock.leaveBusy();
        }
    
<methods>public void collectGridNodeData(org.apache.ignite.spi.discovery.DiscoveryDataBag) ,public void collectJoiningNodeData(org.apache.ignite.spi.discovery.DiscoveryDataBag) ,public org.apache.ignite.internal.GridComponent.DiscoveryDataExchangeType discoveryDataType() ,public boolean enabled() ,public void onAfterSpiStart() ,public void onBeforeSpiStart() ,public void onDisconnected(IgniteFuture<?>) throws org.apache.ignite.IgniteCheckedException,public void onGridDataReceived(org.apache.ignite.spi.discovery.DiscoveryDataBag.GridDiscoveryData) ,public void onJoiningNodeDataReceived(org.apache.ignite.spi.discovery.DiscoveryDataBag.JoiningNodeDiscoveryData) ,public final void onKernalStart(boolean) throws org.apache.ignite.IgniteCheckedException,public final void onKernalStop(boolean) ,public IgniteInternalFuture<?> onReconnected(boolean) throws org.apache.ignite.IgniteCheckedException,public void printMemoryStats() ,public final java.lang.String toString() ,public org.apache.ignite.spi.IgniteNodeValidationResult validateNode(org.apache.ignite.cluster.ClusterNode) ,public org.apache.ignite.spi.IgniteNodeValidationResult validateNode(org.apache.ignite.cluster.ClusterNode, org.apache.ignite.spi.discovery.DiscoveryDataBag.JoiningNodeDiscoveryData) <variables>protected final non-sealed org.apache.ignite.internal.GridKernalContext ctx,private final non-sealed boolean enabled,private boolean injected,protected final non-sealed org.apache.ignite.IgniteLogger log,private final Map<org.apache.ignite.spi.IgniteSpi,java.lang.Boolean> spiMap,private final non-sealed org.apache.ignite.spi.indexing.IndexingSpi[] spis