Search in sources :

Example 1 with OriginalIndices

use of org.opensearch.action.OriginalIndices in project OpenSearch by opensearch-project.

the class TransportSearchAction method getRemoteShardsIterator.

static List<SearchShardIterator> getRemoteShardsIterator(Map<String, ClusterSearchShardsResponse> searchShardsResponses, Map<String, OriginalIndices> remoteIndicesByCluster, Map<String, AliasFilter> aliasFilterMap) {
    final List<SearchShardIterator> remoteShardIterators = new ArrayList<>();
    for (Map.Entry<String, ClusterSearchShardsResponse> entry : searchShardsResponses.entrySet()) {
        for (ClusterSearchShardsGroup clusterSearchShardsGroup : entry.getValue().getGroups()) {
            // add the cluster name to the remote index names for indices disambiguation
            // this ends up in the hits returned with the search response
            ShardId shardId = clusterSearchShardsGroup.getShardId();
            AliasFilter aliasFilter = aliasFilterMap.get(shardId.getIndex().getUUID());
            String[] aliases = aliasFilter.getAliases();
            String clusterAlias = entry.getKey();
            String[] finalIndices = aliases.length == 0 ? new String[] { shardId.getIndexName() } : aliases;
            final OriginalIndices originalIndices = remoteIndicesByCluster.get(clusterAlias);
            assert originalIndices != null : "original indices are null for clusterAlias: " + clusterAlias;
            SearchShardIterator shardIterator = new SearchShardIterator(clusterAlias, shardId, Arrays.asList(clusterSearchShardsGroup.getShards()), new OriginalIndices(finalIndices, originalIndices.indicesOptions()));
            remoteShardIterators.add(shardIterator);
        }
    }
    return remoteShardIterators;
}
Also used : ClusterSearchShardsResponse(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse) ShardId(org.opensearch.index.shard.ShardId) AliasFilter(org.opensearch.search.internal.AliasFilter) ArrayList(java.util.ArrayList) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ClusterSearchShardsGroup(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsGroup) OriginalIndices(org.opensearch.action.OriginalIndices)

Example 2 with OriginalIndices

use of org.opensearch.action.OriginalIndices in project OpenSearch by opensearch-project.

the class TransportSearchAction method collectSearchShards.

static void collectSearchShards(IndicesOptions indicesOptions, String preference, String routing, AtomicInteger skippedClusters, Map<String, OriginalIndices> remoteIndicesByCluster, RemoteClusterService remoteClusterService, ThreadPool threadPool, ActionListener<Map<String, ClusterSearchShardsResponse>> listener) {
    final CountDown responsesCountDown = new CountDown(remoteIndicesByCluster.size());
    final Map<String, ClusterSearchShardsResponse> searchShardsResponses = new ConcurrentHashMap<>();
    final AtomicReference<Exception> exceptions = new AtomicReference<>();
    for (Map.Entry<String, OriginalIndices> entry : remoteIndicesByCluster.entrySet()) {
        final String clusterAlias = entry.getKey();
        boolean skipUnavailable = remoteClusterService.isSkipUnavailable(clusterAlias);
        Client clusterClient = remoteClusterService.getRemoteClusterClient(threadPool, clusterAlias);
        final String[] indices = entry.getValue().indices();
        ClusterSearchShardsRequest searchShardsRequest = new ClusterSearchShardsRequest(indices).indicesOptions(indicesOptions).local(true).preference(preference).routing(routing);
        clusterClient.admin().cluster().searchShards(searchShardsRequest, new CCSActionListener<ClusterSearchShardsResponse, Map<String, ClusterSearchShardsResponse>>(clusterAlias, skipUnavailable, responsesCountDown, skippedClusters, exceptions, listener) {

            @Override
            void innerOnResponse(ClusterSearchShardsResponse clusterSearchShardsResponse) {
                searchShardsResponses.put(clusterAlias, clusterSearchShardsResponse);
            }

            @Override
            Map<String, ClusterSearchShardsResponse> createFinalResponse() {
                return searchShardsResponses;
            }
        });
    }
}
Also used : ClusterSearchShardsResponse(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDown(org.opensearch.common.util.concurrent.CountDown) RemoteTransportException(org.opensearch.transport.RemoteTransportException) ClusterBlockException(org.opensearch.cluster.block.ClusterBlockException) ClusterSearchShardsRequest(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsRequest) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Client(org.opensearch.client.Client) NodeClient(org.opensearch.client.node.NodeClient) OriginSettingClient(org.opensearch.client.OriginSettingClient) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) OriginalIndices(org.opensearch.action.OriginalIndices)

Example 3 with OriginalIndices

use of org.opensearch.action.OriginalIndices in project OpenSearch by opensearch-project.

the class RemoteClusterService method groupIndices.

public Map<String, OriginalIndices> groupIndices(IndicesOptions indicesOptions, String[] indices, Predicate<String> indexExists) {
    Map<String, OriginalIndices> originalIndicesMap = new HashMap<>();
    if (isCrossClusterSearchEnabled()) {
        final Map<String, List<String>> groupedIndices = groupClusterIndices(getRemoteClusterNames(), indices, indexExists);
        if (groupedIndices.isEmpty()) {
            // search on _all in the local cluster if neither local indices nor remote indices were specified
            originalIndicesMap.put(LOCAL_CLUSTER_GROUP_KEY, new OriginalIndices(Strings.EMPTY_ARRAY, indicesOptions));
        } else {
            for (Map.Entry<String, List<String>> entry : groupedIndices.entrySet()) {
                String clusterAlias = entry.getKey();
                List<String> originalIndices = entry.getValue();
                originalIndicesMap.put(clusterAlias, new OriginalIndices(originalIndices.toArray(new String[0]), indicesOptions));
            }
        }
    } else {
        originalIndicesMap.put(LOCAL_CLUSTER_GROUP_KEY, new OriginalIndices(indices, indicesOptions));
    }
    return originalIndicesMap;
}
Also used : HashMap(java.util.HashMap) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) OriginalIndices(org.opensearch.action.OriginalIndices)

Example 4 with OriginalIndices

use of org.opensearch.action.OriginalIndices in project OpenSearch by opensearch-project.

the class TransportSearchActionTests method testCollectSearchShards.

public void testCollectSearchShards() throws Exception {
    int numClusters = randomIntBetween(2, 10);
    DiscoveryNode[] nodes = new DiscoveryNode[numClusters];
    Map<String, OriginalIndices> remoteIndicesByCluster = new HashMap<>();
    Settings.Builder builder = Settings.builder();
    MockTransportService[] mockTransportServices = startTransport(numClusters, nodes, remoteIndicesByCluster, builder);
    Settings settings = builder.build();
    try (MockTransportService service = MockTransportService.createNewService(settings, Version.CURRENT, threadPool, null)) {
        service.start();
        service.acceptIncomingRequests();
        RemoteClusterService remoteClusterService = service.getRemoteClusterService();
        {
            final CountDownLatch latch = new CountDownLatch(1);
            AtomicReference<Map<String, ClusterSearchShardsResponse>> response = new AtomicReference<>();
            AtomicInteger skippedClusters = new AtomicInteger();
            TransportSearchAction.collectSearchShards(IndicesOptions.lenientExpandOpen(), null, null, skippedClusters, remoteIndicesByCluster, remoteClusterService, threadPool, new LatchedActionListener<>(ActionListener.wrap(response::set, e -> fail("no failures expected")), latch));
            awaitLatch(latch, 5, TimeUnit.SECONDS);
            assertEquals(0, skippedClusters.get());
            assertNotNull(response.get());
            Map<String, ClusterSearchShardsResponse> map = response.get();
            assertEquals(numClusters, map.size());
            for (int i = 0; i < numClusters; i++) {
                String clusterAlias = "remote" + i;
                assertTrue(map.containsKey(clusterAlias));
                ClusterSearchShardsResponse shardsResponse = map.get(clusterAlias);
                assertEquals(1, shardsResponse.getNodes().length);
            }
        }
        {
            final CountDownLatch latch = new CountDownLatch(1);
            AtomicReference<Exception> failure = new AtomicReference<>();
            AtomicInteger skippedClusters = new AtomicInteger(0);
            TransportSearchAction.collectSearchShards(IndicesOptions.lenientExpandOpen(), "index_not_found", null, skippedClusters, remoteIndicesByCluster, remoteClusterService, threadPool, new LatchedActionListener<>(ActionListener.wrap(r -> fail("no response expected"), failure::set), latch));
            awaitLatch(latch, 5, TimeUnit.SECONDS);
            assertEquals(0, skippedClusters.get());
            assertNotNull(failure.get());
            assertThat(failure.get(), instanceOf(RemoteTransportException.class));
            RemoteTransportException remoteTransportException = (RemoteTransportException) failure.get();
            assertEquals(RestStatus.NOT_FOUND, remoteTransportException.status());
        }
        int numDisconnectedClusters = randomIntBetween(1, numClusters);
        Set<DiscoveryNode> disconnectedNodes = new HashSet<>(numDisconnectedClusters);
        Set<Integer> disconnectedNodesIndices = new HashSet<>(numDisconnectedClusters);
        while (disconnectedNodes.size() < numDisconnectedClusters) {
            int i = randomIntBetween(0, numClusters - 1);
            if (disconnectedNodes.add(nodes[i])) {
                assertTrue(disconnectedNodesIndices.add(i));
            }
        }
        CountDownLatch disconnectedLatch = new CountDownLatch(numDisconnectedClusters);
        RemoteClusterServiceTests.addConnectionListener(remoteClusterService, new TransportConnectionListener() {

            @Override
            public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) {
                if (disconnectedNodes.remove(node)) {
                    disconnectedLatch.countDown();
                }
            }
        });
        for (DiscoveryNode disconnectedNode : disconnectedNodes) {
            service.addFailToSendNoConnectRule(disconnectedNode.getAddress());
        }
        {
            final CountDownLatch latch = new CountDownLatch(1);
            AtomicInteger skippedClusters = new AtomicInteger(0);
            AtomicReference<Exception> failure = new AtomicReference<>();
            TransportSearchAction.collectSearchShards(IndicesOptions.lenientExpandOpen(), null, null, skippedClusters, remoteIndicesByCluster, remoteClusterService, threadPool, new LatchedActionListener<>(ActionListener.wrap(r -> fail("no response expected"), failure::set), latch));
            awaitLatch(latch, 5, TimeUnit.SECONDS);
            assertEquals(0, skippedClusters.get());
            assertNotNull(failure.get());
            assertThat(failure.get(), instanceOf(RemoteTransportException.class));
            assertThat(failure.get().getMessage(), containsString("error while communicating with remote cluster ["));
            assertThat(failure.get().getCause(), instanceOf(NodeDisconnectedException.class));
        }
        // setting skip_unavailable to true for all the disconnected clusters will make the request succeed again
        for (int i : disconnectedNodesIndices) {
            RemoteClusterServiceTests.updateSkipUnavailable(remoteClusterService, "remote" + i, true);
        }
        {
            final CountDownLatch latch = new CountDownLatch(1);
            AtomicInteger skippedClusters = new AtomicInteger(0);
            AtomicReference<Map<String, ClusterSearchShardsResponse>> response = new AtomicReference<>();
            TransportSearchAction.collectSearchShards(IndicesOptions.lenientExpandOpen(), null, null, skippedClusters, remoteIndicesByCluster, remoteClusterService, threadPool, new LatchedActionListener<>(ActionListener.wrap(response::set, e -> fail("no failures expected")), latch));
            awaitLatch(latch, 5, TimeUnit.SECONDS);
            assertNotNull(response.get());
            Map<String, ClusterSearchShardsResponse> map = response.get();
            assertEquals(numClusters - disconnectedNodesIndices.size(), map.size());
            assertEquals(skippedClusters.get(), disconnectedNodesIndices.size());
            for (int i = 0; i < numClusters; i++) {
                String clusterAlias = "remote" + i;
                if (disconnectedNodesIndices.contains(i)) {
                    assertFalse(map.containsKey(clusterAlias));
                } else {
                    assertNotNull(map.get(clusterAlias));
                }
            }
        }
        // give transport service enough time to realize that the node is down, and to notify the connection listeners
        // so that RemoteClusterConnection is left with no connected nodes, hence it will retry connecting next
        assertTrue(disconnectedLatch.await(5, TimeUnit.SECONDS));
        service.clearAllRules();
        if (randomBoolean()) {
            for (int i : disconnectedNodesIndices) {
                if (randomBoolean()) {
                    RemoteClusterServiceTests.updateSkipUnavailable(remoteClusterService, "remote" + i, true);
                }
            }
        }
        {
            final CountDownLatch latch = new CountDownLatch(1);
            AtomicInteger skippedClusters = new AtomicInteger(0);
            AtomicReference<Map<String, ClusterSearchShardsResponse>> response = new AtomicReference<>();
            TransportSearchAction.collectSearchShards(IndicesOptions.lenientExpandOpen(), null, null, skippedClusters, remoteIndicesByCluster, remoteClusterService, threadPool, new LatchedActionListener<>(ActionListener.wrap(response::set, e -> fail("no failures expected")), latch));
            awaitLatch(latch, 5, TimeUnit.SECONDS);
            assertEquals(0, skippedClusters.get());
            assertNotNull(response.get());
            Map<String, ClusterSearchShardsResponse> map = response.get();
            assertEquals(numClusters, map.size());
            for (int i = 0; i < numClusters; i++) {
                String clusterAlias = "remote" + i;
                assertTrue(map.containsKey(clusterAlias));
                assertNotNull(map.get(clusterAlias));
            }
        }
        assertEquals(0, service.getConnectionManager().size());
    } finally {
        for (MockTransportService mockTransportService : mockTransportServices) {
            mockTransportService.close();
        }
    }
}
Also used : ClusterSearchShardsResponse(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse) Arrays(java.util.Arrays) SearchContext(org.opensearch.search.internal.SearchContext) BiFunction(java.util.function.BiFunction) TestThreadPool(org.opensearch.threadpool.TestThreadPool) SortBuilders(org.opensearch.search.sort.SortBuilders) Version(org.opensearch.Version) ClusterSearchShardsResponse(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsResponse) CoreMatchers.startsWith(org.hamcrest.CoreMatchers.startsWith) Strings(org.opensearch.common.Strings) Transport(org.opensearch.transport.Transport) CoreMatchers.instanceOf(org.hamcrest.CoreMatchers.instanceOf) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) LatchedActionListener(org.opensearch.action.LatchedActionListener) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InternalAggregations(org.opensearch.search.aggregations.InternalAggregations) AliasFilter(org.opensearch.search.internal.AliasFilter) Map(java.util.Map) ActionListener(org.opensearch.action.ActionListener) Scroll(org.opensearch.search.Scroll) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) OpenSearchAssertions.awaitLatch(org.opensearch.test.hamcrest.OpenSearchAssertions.awaitLatch) InternalAggregationTestCase.emptyReduceContextBuilder(org.opensearch.test.InternalAggregationTestCase.emptyReduceContextBuilder) Index(org.opensearch.index.Index) SearchHit(org.opensearch.search.SearchHit) OpenSearchTestCase(org.opensearch.test.OpenSearchTestCase) RemoteTransportException(org.opensearch.transport.RemoteTransportException) TransportRequestOptions(org.opensearch.transport.TransportRequestOptions) InnerHitBuilder(org.opensearch.index.query.InnerHitBuilder) Set(java.util.Set) Settings(org.opensearch.common.settings.Settings) RestStatus(org.opensearch.rest.RestStatus) TransportService(org.opensearch.transport.TransportService) OriginalIndices(org.opensearch.action.OriginalIndices) Tuple(org.opensearch.common.collect.Tuple) TransportAddress(org.opensearch.common.transport.TransportAddress) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) NodeDisconnectedException(org.opensearch.transport.NodeDisconnectedException) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) CollapseBuilder(org.opensearch.search.collapse.CollapseBuilder) TermsQueryBuilder(org.opensearch.index.query.TermsQueryBuilder) InternalAggregation(org.opensearch.search.aggregations.InternalAggregation) TransportException(org.opensearch.transport.TransportException) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) RemoteClusterServiceTests(org.opensearch.transport.RemoteClusterServiceTests) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) ThreadPool(org.opensearch.threadpool.ThreadPool) GroupShardsIteratorTests(org.opensearch.cluster.routing.GroupShardsIteratorTests) HashMap(java.util.HashMap) SearchHits(org.opensearch.search.SearchHits) IndicesOptions(org.opensearch.action.support.IndicesOptions) MockTransportService(org.opensearch.test.transport.MockTransportService) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClusterState(org.opensearch.cluster.ClusterState) ShardRoutingState(org.opensearch.cluster.routing.ShardRoutingState) ClusterBlocks(org.opensearch.cluster.block.ClusterBlocks) QueryBuilders(org.opensearch.index.query.QueryBuilders) SetOnce(org.apache.lucene.util.SetOnce) RemoteClusterService(org.opensearch.transport.RemoteClusterService) TransportRequest(org.opensearch.transport.TransportRequest) TransportConnectionListener(org.opensearch.transport.TransportConnectionListener) InternalSearchResponse(org.opensearch.search.internal.InternalSearchResponse) ClusterSearchShardsGroup(org.opensearch.action.admin.cluster.shards.ClusterSearchShardsGroup) TotalHits(org.apache.lucene.search.TotalHits) ShardRouting(org.opensearch.cluster.routing.ShardRouting) ShardId(org.opensearch.index.shard.ShardId) TimeUnit(java.util.concurrent.TimeUnit) GroupShardsIterator(org.opensearch.cluster.routing.GroupShardsIterator) TestShardRouting(org.opensearch.cluster.routing.TestShardRouting) SearchShardTarget(org.opensearch.search.SearchShardTarget) RemoteClusterConnectionTests(org.opensearch.transport.RemoteClusterConnectionTests) ClusterName(org.opensearch.cluster.ClusterName) OriginalIndicesTests(org.opensearch.action.OriginalIndicesTests) MatchAllQueryBuilder(org.opensearch.index.query.MatchAllQueryBuilder) Collections(java.util.Collections) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) MockTransportService(org.opensearch.test.transport.MockTransportService) HashMap(java.util.HashMap) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) TransportConnectionListener(org.opensearch.transport.TransportConnectionListener) LatchedActionListener(org.opensearch.action.LatchedActionListener) Settings(org.opensearch.common.settings.Settings) HashSet(java.util.HashSet) RemoteTransportException(org.opensearch.transport.RemoteTransportException) RemoteClusterService(org.opensearch.transport.RemoteClusterService) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Transport(org.opensearch.transport.Transport) Map(java.util.Map) HashMap(java.util.HashMap) OriginalIndices(org.opensearch.action.OriginalIndices)

Example 5 with OriginalIndices

use of org.opensearch.action.OriginalIndices in project OpenSearch by opensearch-project.

the class TransportSearchActionTests method startTransport.

private MockTransportService[] startTransport(int numClusters, DiscoveryNode[] nodes, Map<String, OriginalIndices> remoteIndices, Settings.Builder settingsBuilder) {
    MockTransportService[] mockTransportServices = new MockTransportService[numClusters];
    for (int i = 0; i < numClusters; i++) {
        List<DiscoveryNode> knownNodes = new CopyOnWriteArrayList<>();
        MockTransportService remoteSeedTransport = RemoteClusterConnectionTests.startTransport("node_remote" + i, knownNodes, Version.CURRENT, threadPool);
        mockTransportServices[i] = remoteSeedTransport;
        DiscoveryNode remoteSeedNode = remoteSeedTransport.getLocalDiscoNode();
        knownNodes.add(remoteSeedNode);
        nodes[i] = remoteSeedNode;
        settingsBuilder.put("cluster.remote.remote" + i + ".seeds", remoteSeedNode.getAddress().toString());
        remoteIndices.put("remote" + i, new OriginalIndices(new String[] { "index" }, IndicesOptions.lenientExpandOpen()));
    }
    return mockTransportServices;
}
Also used : DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) MockTransportService(org.opensearch.test.transport.MockTransportService) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) OriginalIndices(org.opensearch.action.OriginalIndices) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Aggregations

OriginalIndices (org.opensearch.action.OriginalIndices)29 DiscoveryNode (org.opensearch.cluster.node.DiscoveryNode)18 ShardId (org.opensearch.index.shard.ShardId)18 AliasFilter (org.opensearch.search.internal.AliasFilter)18 HashMap (java.util.HashMap)15 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)15 CountDownLatch (java.util.concurrent.CountDownLatch)15 AtomicReference (java.util.concurrent.atomic.AtomicReference)15 SearchShardTarget (org.opensearch.search.SearchShardTarget)14 ArrayList (java.util.ArrayList)12 HashSet (java.util.HashSet)12 ActionListener (org.opensearch.action.ActionListener)12 Map (java.util.Map)11 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)11 InternalSearchResponse (org.opensearch.search.internal.InternalSearchResponse)11 GroupShardsIterator (org.opensearch.cluster.routing.GroupShardsIterator)10 List (java.util.List)9 Set (java.util.Set)9 Collections (java.util.Collections)8 SearchSourceBuilder (org.opensearch.search.builder.SearchSourceBuilder)8