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

solutions.siren.join.action.coordinate.TransportCoordinateMultiSearchAction Maven / Gradle / Ivy

/**
 * Copyright (c) 2016, SIREn Solutions. All Rights Reserved.
 *
 * This file is part of the SIREn project.
 *
 * SIREn is a free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * SIREn is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program. If not, see .
 */
package solutions.siren.join.action.coordinate;

import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.AtomicArray;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import solutions.siren.join.action.admin.cache.FilterJoinCacheService;
import solutions.siren.join.action.coordinate.execution.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * The transport action for a coordinated multi-search. It converts the filter joins defined in all the requests into
 * binary terms filters, reusing cached computation when possible.
 * 
* The {@link #doExecuteRequest(MultiSearchRequest, ActionListener, List)} is a copy of * {@link TransportMultiSearchAction#doExecute(MultiSearchRequest, ActionListener)} where we instantiate a * {@link CoordinateMultiSearchResponse} instead of a {@link MultiSearchResponse}. * * @see TransportMultiSearchAction */ public class TransportCoordinateMultiSearchAction extends BaseTransportCoordinateSearchAction { private final ClusterService clusterService; private final TransportSearchAction searchAction; private final FilterJoinCacheService cacheService; @Inject public TransportCoordinateMultiSearchAction(Settings settings, ThreadPool threadPool, TransportService transportService, ClusterService clusterService, FilterJoinCacheService cacheService, TransportSearchAction search, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver, Client client) { super(settings, CoordinateMultiSearchAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, client, MultiSearchRequest.class); this.searchAction = search; this.clusterService = clusterService; this.cacheService = cacheService; } @Override protected void doExecute(final MultiSearchRequest request, final ActionListener listener) { logger.debug("{}: Execute coordinated multi-search action", Thread.currentThread().getName()); List metadatas = new ArrayList<>(request.requests().size()); this.doExecuteFilterJoins(request, metadatas); this.doExecuteRequest(request, listener, metadatas); logger.debug("{}: Coordinated multi-search action completed", Thread.currentThread().getName()); } private void doExecuteFilterJoins(final MultiSearchRequest request, final List metadatas) { FilterJoinCache cache = cacheService.getCacheInstance(); for (int i = 0; i < request.requests().size(); i++) { // Parse query source Tuple> parsedSource = this.parseSource(request.requests().get(i).source()); Map map = parsedSource.v2(); // Query planning and execution of filter joins SourceMapVisitor mapVisitor = new SourceMapVisitor(map); mapVisitor.traverse(); FilterJoinVisitor joinVisitor = new FilterJoinVisitor(client, mapVisitor.getFilterJoinTree(), cache, request); joinVisitor.traverse(); metadatas.add(joinVisitor.getMetadata()); // Filter joins have been replaced by a binary terms filter // Rebuild the query source, and delegate the execution of the search action request.requests().get(i).source(this.buildSource(parsedSource.v1().xContent(), map)); } } private void doExecuteRequest(final MultiSearchRequest request, final ActionListener listener, final List metadatas) { ClusterState clusterState = clusterService.state(); clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ); final AtomicArray responses = new AtomicArray<>(request.requests().size()); final AtomicInteger counter = new AtomicInteger(responses.length()); for (int i = 0; i < responses.length(); i++) { final int index = i; SearchRequest searchRequest = new SearchRequest(request.requests().get(i), request); searchAction.execute(searchRequest, new ActionListener() { @Override public void onResponse(SearchResponse searchResponse) { responses.set(index, new CoordinateMultiSearchResponse.Item(new CoordinateSearchResponse(searchResponse, metadatas.get(index)), null)); if (counter.decrementAndGet() == 0) { finishHim(); } } @Override public void onFailure(Throwable e) { responses.set(index, new CoordinateMultiSearchResponse.Item(null, ExceptionsHelper.detailedMessage(e))); if (counter.decrementAndGet() == 0) { finishHim(); } } private void finishHim() { listener.onResponse(new CoordinateMultiSearchResponse(responses.toArray(new CoordinateMultiSearchResponse.Item[responses.length()]))); } }); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy