Search in sources :

Example 1 with CountDown

use of org.opensearch.common.util.concurrent.CountDown 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 2 with CountDown

use of org.opensearch.common.util.concurrent.CountDown in project OpenSearch by opensearch-project.

the class SearchScrollAsyncAction method run.

private void run(BiFunction<String, String, DiscoveryNode> clusterNodeLookup, final SearchContextIdForNode[] context) {
    final CountDown counter = new CountDown(scrollId.getContext().length);
    for (int i = 0; i < context.length; i++) {
        SearchContextIdForNode target = context[i];
        final int shardIndex = i;
        final Transport.Connection connection;
        try {
            DiscoveryNode node = clusterNodeLookup.apply(target.getClusterAlias(), target.getNode());
            if (node == null) {
                throw new IllegalStateException("node [" + target.getNode() + "] is not available");
            }
            connection = getConnection(target.getClusterAlias(), node);
        } catch (Exception ex) {
            onShardFailure("query", counter, target.getSearchContextId(), ex, null, () -> SearchScrollAsyncAction.this.moveToNextPhase(clusterNodeLookup));
            continue;
        }
        final InternalScrollSearchRequest internalRequest = TransportSearchHelper.internalScrollSearchRequest(target.getSearchContextId(), request);
        // we can't create a SearchShardTarget here since we don't know the index and shard ID we are talking to
        // we only know the node and the search context ID. Yet, the response will contain the SearchShardTarget
        // from the target node instead...that's why we pass null here
        SearchActionListener<T> searchActionListener = new SearchActionListener<T>(null, shardIndex) {

            @Override
            protected void setSearchShardTarget(T response) {
                // don't do this - it's part of the response...
                assert response.getSearchShardTarget() != null : "search shard target must not be null";
                if (target.getClusterAlias() != null) {
                    // re-create the search target and add the cluster alias if there is any,
                    // we need this down the road for subseq. phases
                    SearchShardTarget searchShardTarget = response.getSearchShardTarget();
                    response.setSearchShardTarget(new SearchShardTarget(searchShardTarget.getNodeId(), searchShardTarget.getShardId(), target.getClusterAlias(), null));
                }
            }

            @Override
            protected void innerOnResponse(T result) {
                assert shardIndex == result.getShardIndex() : "shard index mismatch: " + shardIndex + " but got: " + result.getShardIndex();
                onFirstPhaseResult(shardIndex, result);
                if (counter.countDown()) {
                    SearchPhase phase = moveToNextPhase(clusterNodeLookup);
                    try {
                        phase.run();
                    } catch (Exception e) {
                        // we need to fail the entire request here - the entire phase just blew up
                        // don't call onShardFailure or onFailure here since otherwise we'd countDown the counter
                        // again which would result in an exception
                        listener.onFailure(new SearchPhaseExecutionException(phase.getName(), "Phase failed", e, ShardSearchFailure.EMPTY_ARRAY));
                    }
                }
            }

            @Override
            public void onFailure(Exception t) {
                onShardFailure("query", counter, target.getSearchContextId(), t, null, () -> SearchScrollAsyncAction.this.moveToNextPhase(clusterNodeLookup));
            }
        };
        executeInitialPhase(connection, internalRequest, searchActionListener);
    }
}
Also used : DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) InternalScrollSearchRequest(org.opensearch.search.internal.InternalScrollSearchRequest) CountDown(org.opensearch.common.util.concurrent.CountDown) IOException(java.io.IOException) SearchShardTarget(org.opensearch.search.SearchShardTarget) Transport(org.opensearch.transport.Transport)

Example 3 with CountDown

use of org.opensearch.common.util.concurrent.CountDown in project OpenSearch by opensearch-project.

the class AzureBlobContainerRetriesTests method testReadRangeBlobWithRetries.

public void testReadRangeBlobWithRetries() throws Exception {
    // The request retry policy counts the first attempt as retry, so we need to
    // account for that and increase the max retry count by one.
    final int maxRetries = randomIntBetween(2, 6);
    final CountDown countDownGet = new CountDown(maxRetries - 1);
    final byte[] bytes = randomBlobContent();
    httpServer.createContext("/container/read_range_blob_max_retries", exchange -> {
        try {
            Streams.readFully(exchange.getRequestBody());
            if ("HEAD".equals(exchange.getRequestMethod())) {
                exchange.getResponseHeaders().add("Content-Type", "application/octet-stream");
                exchange.getResponseHeaders().add("Content-Length", String.valueOf(bytes.length));
                exchange.getResponseHeaders().add("x-ms-blob-type", "blockblob");
                exchange.sendResponseHeaders(RestStatus.OK.getStatus(), -1);
                return;
            } else if ("GET".equals(exchange.getRequestMethod())) {
                if (countDownGet.countDown()) {
                    final int rangeStart = getRangeStart(exchange);
                    assertThat(rangeStart, lessThan(bytes.length));
                    final Optional<Integer> rangeEnd = getRangeEnd(exchange);
                    assertThat(rangeEnd.isPresent(), is(true));
                    assertThat(rangeEnd.get(), greaterThanOrEqualTo(rangeStart));
                    final int length = (rangeEnd.get() - rangeStart) + 1;
                    assertThat(length, lessThanOrEqualTo(bytes.length - rangeStart));
                    exchange.getResponseHeaders().add("Content-Type", "application/octet-stream");
                    exchange.getResponseHeaders().add("Content-Length", String.valueOf(length));
                    exchange.getResponseHeaders().add("x-ms-blob-type", "blockblob");
                    exchange.sendResponseHeaders(RestStatus.OK.getStatus(), length);
                    exchange.getResponseBody().write(bytes, rangeStart, length);
                    return;
                }
            }
            if (randomBoolean()) {
                AzureHttpHandler.sendError(exchange, randomFrom(RestStatus.INTERNAL_SERVER_ERROR, RestStatus.SERVICE_UNAVAILABLE));
            }
        } finally {
            exchange.close();
        }
    });
    final BlobContainer blobContainer = createBlobContainer(maxRetries);
    final int position = randomIntBetween(0, bytes.length - 1);
    final int length = randomIntBetween(1, bytes.length - position);
    try (InputStream inputStream = blobContainer.readBlob("read_range_blob_max_retries", position, length)) {
        final byte[] bytesRead = BytesReference.toBytes(Streams.readFully(inputStream));
        assertArrayEquals(Arrays.copyOfRange(bytes, position, Math.min(bytes.length, position + length)), bytesRead);
        assertThat(countDownGet.isCountedDown(), is(true));
    }
}
Also used : Optional(java.util.Optional) InputStream(java.io.InputStream) BlobContainer(org.opensearch.common.blobstore.BlobContainer) CountDown(org.opensearch.common.util.concurrent.CountDown)

Example 4 with CountDown

use of org.opensearch.common.util.concurrent.CountDown in project OpenSearch by opensearch-project.

the class AzureBlobContainerRetriesTests method testWriteLargeBlob.

public void testWriteLargeBlob() throws Exception {
    // The request retry policy counts the first attempt as retry, so we need to
    // account for that and increase the max retry count by one.
    final int maxRetries = randomIntBetween(3, 6);
    final int nbBlocks = randomIntBetween(1, 2);
    final byte[] data = randomBytes(BlobClient.BLOB_DEFAULT_UPLOAD_BLOCK_SIZE * nbBlocks);
    // we want all requests to fail at least once
    final int nbErrors = 2;
    final AtomicInteger countDownUploads = new AtomicInteger(nbErrors * nbBlocks);
    final CountDown countDownComplete = new CountDown(nbErrors);
    final Map<String, BytesReference> blocks = new ConcurrentHashMap<>();
    httpServer.createContext("/container/write_large_blob", exchange -> {
        if ("PUT".equals(exchange.getRequestMethod())) {
            final Map<String, String> params = new HashMap<>();
            if (exchange.getRequestURI().getQuery() != null) {
                RestUtils.decodeQueryString(exchange.getRequestURI().getQuery(), 0, params);
            }
            final String blockId = params.get("blockid");
            if (Strings.hasText(blockId) && (countDownUploads.decrementAndGet() % 2 == 0)) {
                blocks.put(blockId, Streams.readFully(exchange.getRequestBody()));
                exchange.getResponseHeaders().add("x-ms-request-server-encrypted", "false");
                exchange.sendResponseHeaders(RestStatus.CREATED.getStatus(), -1);
                exchange.close();
                return;
            }
            final String complete = params.get("comp");
            if ("blocklist".equals(complete) && (countDownComplete.countDown())) {
                final String blockList = Streams.copyToString(new InputStreamReader(exchange.getRequestBody(), UTF_8));
                final List<String> blockUids = Arrays.stream(blockList.split("<Latest>")).filter(line -> line.contains("</Latest>")).map(line -> line.substring(0, line.indexOf("</Latest>"))).collect(Collectors.toList());
                final ByteArrayOutputStream blob = new ByteArrayOutputStream();
                for (String blockUid : blockUids) {
                    BytesReference block = blocks.remove(blockUid);
                    assert block != null;
                    block.writeTo(blob);
                }
                assertArrayEquals(data, blob.toByteArray());
                exchange.getResponseHeaders().add("x-ms-request-server-encrypted", "false");
                exchange.sendResponseHeaders(RestStatus.CREATED.getStatus(), -1);
                exchange.close();
                return;
            }
        }
        if (randomBoolean()) {
            Streams.readFully(exchange.getRequestBody());
            AzureHttpHandler.sendError(exchange, randomFrom(RestStatus.INTERNAL_SERVER_ERROR, RestStatus.SERVICE_UNAVAILABLE));
        }
        exchange.close();
    });
    final BlobContainer blobContainer = createBlobContainer(maxRetries);
    try (InputStream stream = new InputStreamIndexInput(new ByteArrayIndexInput("desc", data), data.length)) {
        blobContainer.writeBlob("write_large_blob", stream, data.length, false);
    }
    assertThat(countDownUploads.get(), equalTo(0));
    assertThat(countDownComplete.isCountedDown(), is(true));
    assertThat(blocks.isEmpty(), is(true));
}
Also used : BytesReference(org.opensearch.common.bytes.BytesReference) HttpServer(com.sun.net.httpserver.HttpServer) NoSuchFileException(java.nio.file.NoSuchFileException) Arrays(java.util.Arrays) MockSecureSettings(org.opensearch.common.settings.MockSecureSettings) CountDown(org.opensearch.common.util.concurrent.CountDown) KEY_SETTING(org.opensearch.repositories.azure.AzureStorageSettings.KEY_SETTING) TestThreadPool(org.opensearch.threadpool.TestThreadPool) HttpStatus(org.apache.http.HttpStatus) ByteSizeUnit(org.opensearch.common.unit.ByteSizeUnit) Strings(org.opensearch.common.Strings) RequestRetryOptions(com.azure.storage.common.policy.RequestRetryOptions) InetAddress(java.net.InetAddress) Matcher(java.util.regex.Matcher) BlobClient(com.azure.storage.blob.BlobClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Locale(java.util.Locale) After(org.junit.After) Map(java.util.Map) AzureHttpHandler(fixture.azure.AzureHttpHandler) SuppressForbidden(org.opensearch.common.SuppressForbidden) AfterClass(org.junit.AfterClass) TimeValue(org.opensearch.common.unit.TimeValue) MAX_RETRIES_SETTING(org.opensearch.repositories.azure.AzureStorageSettings.MAX_RETRIES_SETTING) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) OpenSearchTestCase(org.opensearch.test.OpenSearchTestCase) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Settings(org.opensearch.common.settings.Settings) RestStatus(org.opensearch.rest.RestStatus) InetSocketAddress(java.net.InetSocketAddress) Collectors(java.util.stream.Collectors) Tuple(org.opensearch.common.collect.Tuple) Objects(java.util.Objects) Base64(java.util.Base64) List(java.util.List) Matchers.equalTo(org.hamcrest.Matchers.equalTo) RetryPolicyType(com.azure.storage.common.policy.RetryPolicyType) Optional(java.util.Optional) Matchers.is(org.hamcrest.Matchers.is) Pattern(java.util.regex.Pattern) ACCOUNT_SETTING(org.opensearch.repositories.azure.AzureStorageSettings.ACCOUNT_SETTING) Matchers.containsString(org.hamcrest.Matchers.containsString) TIMEOUT_SETTING(org.opensearch.repositories.azure.AzureStorageSettings.TIMEOUT_SETTING) ParallelTransferOptions(com.azure.storage.blob.models.ParallelTransferOptions) InetAddresses(org.opensearch.common.network.InetAddresses) BytesReference(org.opensearch.common.bytes.BytesReference) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ThreadPool(org.opensearch.threadpool.ThreadPool) CONTAINER_SETTING(org.opensearch.repositories.azure.AzureRepository.Repository.CONTAINER_SETTING) BlobContainer(org.opensearch.common.blobstore.BlobContainer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) Streams(org.opensearch.common.io.Streams) Matchers.lessThan(org.hamcrest.Matchers.lessThan) Schedulers(reactor.core.scheduler.Schedulers) Before(org.junit.Before) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) InputStreamIndexInput(org.opensearch.common.lucene.store.InputStreamIndexInput) UTF_8(java.nio.charset.StandardCharsets.UTF_8) RepositoryMetadata(org.opensearch.cluster.metadata.RepositoryMetadata) RestUtils(org.opensearch.rest.RestUtils) IOException(java.io.IOException) InputStreamReader(java.io.InputStreamReader) TimeUnit(java.util.concurrent.TimeUnit) BlobPath(org.opensearch.common.blobstore.BlobPath) ByteArrayIndexInput(org.opensearch.common.lucene.store.ByteArrayIndexInput) ENDPOINT_SUFFIX_SETTING(org.opensearch.repositories.azure.AzureStorageSettings.ENDPOINT_SUFFIX_SETTING) HttpExchange(com.sun.net.httpserver.HttpExchange) InputStream(java.io.InputStream) OpenSearchBlobStoreRepositoryIntegTestCase.randomBytes(org.opensearch.repositories.blobstore.OpenSearchBlobStoreRepositoryIntegTestCase.randomBytes) InputStreamReader(java.io.InputStreamReader) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) InputStream(java.io.InputStream) Matchers.containsString(org.hamcrest.Matchers.containsString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteArrayIndexInput(org.opensearch.common.lucene.store.ByteArrayIndexInput) CountDown(org.opensearch.common.util.concurrent.CountDown) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BlobContainer(org.opensearch.common.blobstore.BlobContainer) InputStreamIndexInput(org.opensearch.common.lucene.store.InputStreamIndexInput) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 5 with CountDown

use of org.opensearch.common.util.concurrent.CountDown in project OpenSearch by opensearch-project.

the class S3BlobContainerRetriesTests method testWriteLargeBlob.

public void testWriteLargeBlob() throws Exception {
    final boolean useTimeout = rarely();
    final TimeValue readTimeout = useTimeout ? TimeValue.timeValueMillis(randomIntBetween(100, 500)) : null;
    final ByteSizeValue bufferSize = new ByteSizeValue(5, ByteSizeUnit.MB);
    final BlobContainer blobContainer = createBlobContainer(null, readTimeout, true, bufferSize);
    final int parts = randomIntBetween(1, 5);
    final long lastPartSize = randomLongBetween(10, 512);
    final long blobSize = (parts * bufferSize.getBytes()) + lastPartSize;
    // we want all requests to fail at least once
    final int nbErrors = 2;
    final CountDown countDownInitiate = new CountDown(nbErrors);
    final AtomicInteger countDownUploads = new AtomicInteger(nbErrors * (parts + 1));
    final CountDown countDownComplete = new CountDown(nbErrors);
    httpServer.createContext("/bucket/write_large_blob", exchange -> {
        final long contentLength = Long.parseLong(exchange.getRequestHeaders().getFirst("Content-Length"));
        if ("POST".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getQuery().equals("uploads")) {
            // initiate multipart upload request
            if (countDownInitiate.countDown()) {
                byte[] response = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<InitiateMultipartUploadResult>\n" + "  <Bucket>bucket</Bucket>\n" + "  <Key>write_large_blob</Key>\n" + "  <UploadId>TEST</UploadId>\n" + "</InitiateMultipartUploadResult>").getBytes(StandardCharsets.UTF_8);
                exchange.getResponseHeaders().add("Content-Type", "application/xml");
                exchange.sendResponseHeaders(HttpStatus.SC_OK, response.length);
                exchange.getResponseBody().write(response);
                exchange.close();
                return;
            }
        } else if ("PUT".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getQuery().contains("uploadId=TEST") && exchange.getRequestURI().getQuery().contains("partNumber=")) {
            // upload part request
            MD5DigestCalculatingInputStream md5 = new MD5DigestCalculatingInputStream(exchange.getRequestBody());
            BytesReference bytes = Streams.readFully(md5);
            assertThat((long) bytes.length(), anyOf(equalTo(lastPartSize), equalTo(bufferSize.getBytes())));
            assertThat(contentLength, anyOf(equalTo(lastPartSize), equalTo(bufferSize.getBytes())));
            if (countDownUploads.decrementAndGet() % 2 == 0) {
                exchange.getResponseHeaders().add("ETag", Base16.encodeAsString(md5.getMd5Digest()));
                exchange.sendResponseHeaders(HttpStatus.SC_OK, -1);
                exchange.close();
                return;
            }
        } else if ("POST".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getQuery().equals("uploadId=TEST")) {
            // complete multipart upload request
            if (countDownComplete.countDown()) {
                Streams.readFully(exchange.getRequestBody());
                byte[] response = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<CompleteMultipartUploadResult>\n" + "  <Bucket>bucket</Bucket>\n" + "  <Key>write_large_blob</Key>\n" + "</CompleteMultipartUploadResult>").getBytes(StandardCharsets.UTF_8);
                exchange.getResponseHeaders().add("Content-Type", "application/xml");
                exchange.sendResponseHeaders(HttpStatus.SC_OK, response.length);
                exchange.getResponseBody().write(response);
                exchange.close();
                return;
            }
        }
        // sends an error back or let the request time out
        if (useTimeout == false) {
            if (randomBoolean() && contentLength > 0) {
                Streams.readFully(exchange.getRequestBody(), new byte[randomIntBetween(1, Math.toIntExact(contentLength - 1))]);
            } else {
                Streams.readFully(exchange.getRequestBody());
                exchange.sendResponseHeaders(randomFrom(HttpStatus.SC_INTERNAL_SERVER_ERROR, HttpStatus.SC_BAD_GATEWAY, HttpStatus.SC_SERVICE_UNAVAILABLE, HttpStatus.SC_GATEWAY_TIMEOUT), -1);
            }
            exchange.close();
        }
    });
    blobContainer.writeBlob("write_large_blob", new ZeroInputStream(blobSize), blobSize, false);
    assertThat(countDownInitiate.isCountedDown(), is(true));
    assertThat(countDownUploads.get(), equalTo(0));
    assertThat(countDownComplete.isCountedDown(), is(true));
}
Also used : BytesReference(org.opensearch.common.bytes.BytesReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BlobContainer(org.opensearch.common.blobstore.BlobContainer) MD5DigestCalculatingInputStream(com.amazonaws.services.s3.internal.MD5DigestCalculatingInputStream) ByteSizeValue(org.opensearch.common.unit.ByteSizeValue) CountDown(org.opensearch.common.util.concurrent.CountDown) TimeValue(org.opensearch.common.unit.TimeValue)

Aggregations

CountDown (org.opensearch.common.util.concurrent.CountDown)18 BlobContainer (org.opensearch.common.blobstore.BlobContainer)9 InputStream (java.io.InputStream)8 HashMap (java.util.HashMap)6 Map (java.util.Map)6 TimeValue (org.opensearch.common.unit.TimeValue)6 IOException (java.io.IOException)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Client (org.opensearch.client.Client)5 BytesReference (org.opensearch.common.bytes.BytesReference)5 Arrays (java.util.Arrays)4 ActionListener (org.opensearch.action.ActionListener)4 List (java.util.List)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 OriginalIndices (org.opensearch.action.OriginalIndices)3 DiscoveryNode (org.opensearch.cluster.node.DiscoveryNode)3 Strings (org.opensearch.common.Strings)3 ByteArrayIndexInput (org.opensearch.common.lucene.store.ByteArrayIndexInput)3 InputStreamIndexInput (org.opensearch.common.lucene.store.InputStreamIndexInput)3 MD5DigestCalculatingInputStream (com.amazonaws.services.s3.internal.MD5DigestCalculatingInputStream)2