Search in sources :

Example 6 with CountDown

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

the class AbstractBlobContainerRetriesTestCase method testReadRangeBlobWithRetries.

public void testReadRangeBlobWithRetries() throws Exception {
    final int maxRetries = randomInt(5);
    final CountDown countDown = new CountDown(maxRetries + 1);
    final byte[] bytes = randomBlobContent();
    httpServer.createContext(downloadStorageEndpoint("read_range_blob_max_retries"), exchange -> {
        Streams.readFully(exchange.getRequestBody());
        if (countDown.countDown()) {
            final int rangeStart = getRangeStart(exchange);
            assertThat(rangeStart, lessThan(bytes.length));
            assertTrue(getRangeEnd(exchange).isPresent());
            final int rangeEnd = getRangeEnd(exchange).get();
            assertThat(rangeEnd, greaterThanOrEqualTo(rangeStart));
            // adapt range end to be compliant to https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
            final int effectiveRangeEnd = Math.min(bytes.length - 1, rangeEnd);
            final int length = (effectiveRangeEnd - rangeStart) + 1;
            exchange.getResponseHeaders().add("Content-Type", bytesContentType());
            exchange.sendResponseHeaders(HttpStatus.SC_OK, length);
            exchange.getResponseBody().write(bytes, rangeStart, length);
            exchange.close();
            return;
        }
        if (randomBoolean()) {
            exchange.sendResponseHeaders(randomFrom(HttpStatus.SC_INTERNAL_SERVER_ERROR, HttpStatus.SC_BAD_GATEWAY, HttpStatus.SC_SERVICE_UNAVAILABLE, HttpStatus.SC_GATEWAY_TIMEOUT), -1);
        } else if (randomBoolean()) {
            sendIncompleteContent(exchange, bytes);
        }
        if (randomBoolean()) {
            exchange.close();
        }
    });
    final TimeValue readTimeout = TimeValue.timeValueMillis(between(100, 500));
    final BlobContainer blobContainer = createBlobContainer(maxRetries, readTimeout, null, null);
    final int position = randomIntBetween(0, bytes.length - 1);
    final int length = randomIntBetween(0, randomBoolean() ? bytes.length : Integer.MAX_VALUE);
    try (InputStream inputStream = blobContainer.readBlob("read_range_blob_max_retries", position, length)) {
        final int readLimit;
        final InputStream wrappedStream;
        if (randomBoolean()) {
            // read stream only partly
            readLimit = randomIntBetween(0, length);
            wrappedStream = Streams.limitStream(inputStream, readLimit);
        } else {
            readLimit = length;
            wrappedStream = inputStream;
        }
        final byte[] bytesRead = BytesReference.toBytes(Streams.readFully(wrappedStream));
        logger.info("maxRetries={}, position={}, length={}, readLimit={}, byteSize={}, bytesRead={}", maxRetries, position, length, readLimit, bytes.length, bytesRead.length);
        assertArrayEquals(Arrays.copyOfRange(bytes, position, Math.min(bytes.length, position + readLimit)), bytesRead);
        if (readLimit == 0 || (readLimit < length && readLimit == bytesRead.length)) {
        // we might have completed things based on an incomplete response, and we're happy with that
        } else {
            assertTrue(countDown.isCountedDown());
        }
    }
}
Also used : InputStream(java.io.InputStream) BlobContainer(org.opensearch.common.blobstore.BlobContainer) CountDown(org.opensearch.common.util.concurrent.CountDown) TimeValue(org.opensearch.common.unit.TimeValue)

Example 7 with CountDown

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

the class QueryRewriteContext method executeAsyncActions.

/**
 * Executes all registered async actions and notifies the listener once it's done. The value that is passed to the listener is always
 * <code>null</code>. The list of registered actions is cleared once this method returns.
 */
public void executeAsyncActions(ActionListener listener) {
    if (asyncActions.isEmpty()) {
        listener.onResponse(null);
    } else {
        CountDown countDown = new CountDown(asyncActions.size());
        ActionListener<?> internalListener = new ActionListener() {

            @Override
            public void onResponse(Object o) {
                if (countDown.countDown()) {
                    listener.onResponse(null);
                }
            }

            @Override
            public void onFailure(Exception e) {
                if (countDown.fastForward()) {
                    listener.onFailure(e);
                }
            }
        };
        // make a copy to prevent concurrent modification exception
        List<BiConsumer<Client, ActionListener<?>>> biConsumers = new ArrayList<>(asyncActions);
        asyncActions.clear();
        for (BiConsumer<Client, ActionListener<?>> action : biConsumers) {
            action.accept(client, internalListener);
        }
    }
}
Also used : ActionListener(org.opensearch.action.ActionListener) ArrayList(java.util.ArrayList) Client(org.opensearch.client.Client) CountDown(org.opensearch.common.util.concurrent.CountDown) BiConsumer(java.util.function.BiConsumer)

Example 8 with CountDown

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

the class S3BlobContainerRetriesTests method testWriteBlobWithRetries.

public void testWriteBlobWithRetries() throws Exception {
    final int maxRetries = randomInt(5);
    final CountDown countDown = new CountDown(maxRetries + 1);
    final byte[] bytes = randomBlobContent();
    httpServer.createContext("/bucket/write_blob_max_retries", exchange -> {
        if ("PUT".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getQuery() == null) {
            if (countDown.countDown()) {
                final BytesReference body = Streams.readFully(exchange.getRequestBody());
                if (Objects.deepEquals(bytes, BytesReference.toBytes(body))) {
                    exchange.sendResponseHeaders(HttpStatus.SC_OK, -1);
                } else {
                    exchange.sendResponseHeaders(HttpStatus.SC_BAD_REQUEST, -1);
                }
                exchange.close();
                return;
            }
            if (randomBoolean()) {
                if (randomBoolean()) {
                    Streams.readFully(exchange.getRequestBody(), new byte[randomIntBetween(1, Math.max(1, bytes.length - 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();
        }
    });
    final BlobContainer blobContainer = createBlobContainer(maxRetries, null, true, null);
    try (InputStream stream = new InputStreamIndexInput(new ByteArrayIndexInput("desc", bytes), bytes.length)) {
        blobContainer.writeBlob("write_blob_max_retries", stream, bytes.length, false);
    }
    assertThat(countDown.isCountedDown(), is(true));
}
Also used : BytesReference(org.opensearch.common.bytes.BytesReference) FilterInputStream(java.io.FilterInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) MD5DigestCalculatingInputStream(com.amazonaws.services.s3.internal.MD5DigestCalculatingInputStream) InputStream(java.io.InputStream) BlobContainer(org.opensearch.common.blobstore.BlobContainer) InputStreamIndexInput(org.opensearch.common.lucene.store.InputStreamIndexInput) ByteArrayIndexInput(org.opensearch.common.lucene.store.ByteArrayIndexInput) CountDown(org.opensearch.common.util.concurrent.CountDown)

Example 9 with CountDown

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

the class TransportFieldCapabilitiesAction method doExecute.

@Override
protected void doExecute(Task task, FieldCapabilitiesRequest request, final ActionListener<FieldCapabilitiesResponse> listener) {
    // retrieve the initial timestamp in case the action is a cross cluster search
    long nowInMillis = request.nowInMillis() == null ? System.currentTimeMillis() : request.nowInMillis();
    final ClusterState clusterState = clusterService.state();
    final Map<String, OriginalIndices> remoteClusterIndices = remoteClusterService.groupIndices(request.indicesOptions(), request.indices(), idx -> indexNameExpressionResolver.hasIndexAbstraction(idx, clusterState));
    final OriginalIndices localIndices = remoteClusterIndices.remove(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY);
    final String[] concreteIndices;
    if (localIndices == null) {
        // in the case we have one or more remote indices but no local we don't expand to all local indices and just do remote indices
        concreteIndices = Strings.EMPTY_ARRAY;
    } else {
        concreteIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, localIndices);
    }
    final int totalNumRequest = concreteIndices.length + remoteClusterIndices.size();
    final CountDown completionCounter = new CountDown(totalNumRequest);
    final List<FieldCapabilitiesIndexResponse> indexResponses = Collections.synchronizedList(new ArrayList<>());
    final Runnable onResponse = () -> {
        if (completionCounter.countDown()) {
            if (request.isMergeResults()) {
                listener.onResponse(merge(indexResponses, request.includeUnmapped()));
            } else {
                listener.onResponse(new FieldCapabilitiesResponse(indexResponses));
            }
        }
    };
    if (totalNumRequest == 0) {
        listener.onResponse(new FieldCapabilitiesResponse(new String[0], Collections.emptyMap()));
    } else {
        ActionListener<FieldCapabilitiesIndexResponse> innerListener = new ActionListener<FieldCapabilitiesIndexResponse>() {

            @Override
            public void onResponse(FieldCapabilitiesIndexResponse result) {
                if (result.canMatch()) {
                    indexResponses.add(result);
                }
                onResponse.run();
            }

            @Override
            public void onFailure(Exception e) {
                // TODO we should somehow inform the user that we failed
                onResponse.run();
            }
        };
        for (String index : concreteIndices) {
            shardAction.execute(new FieldCapabilitiesIndexRequest(request.fields(), index, localIndices, request.indexFilter(), nowInMillis), innerListener);
        }
        // send us back all individual index results.
        for (Map.Entry<String, OriginalIndices> remoteIndices : remoteClusterIndices.entrySet()) {
            String clusterAlias = remoteIndices.getKey();
            OriginalIndices originalIndices = remoteIndices.getValue();
            Client remoteClusterClient = remoteClusterService.getRemoteClusterClient(threadPool, clusterAlias);
            FieldCapabilitiesRequest remoteRequest = new FieldCapabilitiesRequest();
            // we need to merge on this node
            remoteRequest.setMergeResults(false);
            remoteRequest.indicesOptions(originalIndices.indicesOptions());
            remoteRequest.indices(originalIndices.indices());
            remoteRequest.fields(request.fields());
            remoteRequest.indexFilter(request.indexFilter());
            remoteRequest.nowInMillis(nowInMillis);
            remoteClusterClient.fieldCaps(remoteRequest, ActionListener.wrap(response -> {
                for (FieldCapabilitiesIndexResponse res : response.getIndexResponses()) {
                    indexResponses.add(new FieldCapabilitiesIndexResponse(RemoteClusterAware.buildRemoteIndexName(clusterAlias, res.getIndexName()), res.get(), res.canMatch()));
                }
                onResponse.run();
            }, failure -> onResponse.run()));
        }
    }
}
Also used : RemoteClusterAware(org.opensearch.transport.RemoteClusterAware) Client(org.opensearch.client.Client) Arrays(java.util.Arrays) HandledTransportAction(org.opensearch.action.support.HandledTransportAction) RemoteClusterService(org.opensearch.transport.RemoteClusterService) CountDown(org.opensearch.common.util.concurrent.CountDown) ThreadPool(org.opensearch.threadpool.ThreadPool) Set(java.util.Set) HashMap(java.util.HashMap) Task(org.opensearch.tasks.Task) TransportService(org.opensearch.transport.TransportService) OriginalIndices(org.opensearch.action.OriginalIndices) Strings(org.opensearch.common.Strings) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ActionFilters(org.opensearch.action.support.ActionFilters) ClusterState(org.opensearch.cluster.ClusterState) List(java.util.List) Map(java.util.Map) ClusterService(org.opensearch.cluster.service.ClusterService) Inject(org.opensearch.common.inject.Inject) ActionListener(org.opensearch.action.ActionListener) Collections(java.util.Collections) IndexNameExpressionResolver(org.opensearch.cluster.metadata.IndexNameExpressionResolver) ClusterState(org.opensearch.cluster.ClusterState) CountDown(org.opensearch.common.util.concurrent.CountDown) ActionListener(org.opensearch.action.ActionListener) Client(org.opensearch.client.Client) HashMap(java.util.HashMap) Map(java.util.Map) OriginalIndices(org.opensearch.action.OriginalIndices)

Example 10 with CountDown

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

the class GoogleCloudStorageBlobContainerRetriesTests method testWriteBlobWithRetries.

public void testWriteBlobWithRetries() throws Exception {
    final int maxRetries = randomIntBetween(2, 10);
    final CountDown countDown = new CountDown(maxRetries);
    final byte[] bytes = randomBlobContent();
    httpServer.createContext("/upload/storage/v1/b/bucket/o", safeHandler(exchange -> {
        assertThat(exchange.getRequestURI().getQuery(), containsString("uploadType=multipart"));
        if (countDown.countDown()) {
            Optional<Tuple<String, BytesReference>> content = parseMultipartRequestBody(exchange.getRequestBody());
            assertThat(content.isPresent(), is(true));
            assertThat(content.get().v1(), equalTo("write_blob_max_retries"));
            if (Objects.deepEquals(bytes, BytesReference.toBytes(content.get().v2()))) {
                byte[] response = ("{\"bucket\":\"bucket\",\"name\":\"" + content.get().v1() + "\"}").getBytes(UTF_8);
                exchange.getResponseHeaders().add("Content-Type", "application/json");
                exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length);
                exchange.getResponseBody().write(response);
            } else {
                exchange.sendResponseHeaders(HttpStatus.SC_BAD_REQUEST, -1);
            }
            return;
        }
        if (randomBoolean()) {
            if (randomBoolean()) {
                Streams.readFully(exchange.getRequestBody(), new byte[randomIntBetween(1, Math.max(1, bytes.length - 1))]);
            } else {
                Streams.readFully(exchange.getRequestBody());
                exchange.sendResponseHeaders(HttpStatus.SC_INTERNAL_SERVER_ERROR, -1);
            }
        }
    }));
    final BlobContainer blobContainer = createBlobContainer(maxRetries, null, null, null);
    try (InputStream stream = new InputStreamIndexInput(new ByteArrayIndexInput("desc", bytes), bytes.length)) {
        blobContainer.writeBlob("write_blob_max_retries", stream, bytes.length, false);
    }
    assertThat(countDown.isCountedDown(), is(true));
}
Also used : Arrays(java.util.Arrays) MockSecureSettings(org.opensearch.common.settings.MockSecureSettings) CountDown(org.opensearch.common.util.concurrent.CountDown) HttpStatus(org.apache.http.HttpStatus) StorageOptions(com.google.cloud.storage.StorageOptions) Strings(org.opensearch.common.Strings) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Locale(java.util.Locale) Map(java.util.Map) TOKEN_URI_SETTING(org.opensearch.repositories.gcs.GoogleCloudStorageClientSettings.TOKEN_URI_SETTING) SuppressForbidden(org.opensearch.common.SuppressForbidden) TimeValue(org.opensearch.common.unit.TimeValue) OpenSearchMockAPIBasedRepositoryIntegTestCase(org.opensearch.repositories.blobstore.OpenSearchMockAPIBasedRepositoryIntegTestCase) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) Settings(org.opensearch.common.settings.Settings) RestStatus(org.opensearch.rest.RestStatus) InetSocketAddress(java.net.InetSocketAddress) Nullable(org.opensearch.common.Nullable) Tuple(org.opensearch.common.collect.Tuple) Duration(org.threeten.bp.Duration) Objects(java.util.Objects) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) BytesArray(org.opensearch.common.bytes.BytesArray) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Optional(java.util.Optional) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.is(org.hamcrest.Matchers.is) Matchers.anyOf(org.hamcrest.Matchers.anyOf) Matchers.containsString(org.hamcrest.Matchers.containsString) InetAddresses(org.opensearch.common.network.InetAddresses) BytesReference(org.opensearch.common.bytes.BytesReference) BeforeClass(org.junit.BeforeClass) BlobContainer(org.opensearch.common.blobstore.BlobContainer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ByteSizeValue(org.opensearch.common.unit.ByteSizeValue) HashMap(java.util.HashMap) GoogleCloudStorageHttpHandler.getContentRangeEnd(fixture.gcs.GoogleCloudStorageHttpHandler.getContentRangeEnd) AtomicReference(java.util.concurrent.atomic.AtomicReference) JavaVersion(org.opensearch.bootstrap.JavaVersion) RetrySettings(com.google.api.gax.retrying.RetrySettings) Streams(org.opensearch.common.io.Streams) AbstractBlobContainerRetriesTestCase(org.opensearch.repositories.blobstore.AbstractBlobContainerRetriesTestCase) SocketTimeoutException(java.net.SocketTimeoutException) GoogleCloudStorageHttpHandler.parseMultipartRequestBody(fixture.gcs.GoogleCloudStorageHttpHandler.parseMultipartRequestBody) READ_TIMEOUT_SETTING(org.opensearch.repositories.gcs.GoogleCloudStorageClientSettings.READ_TIMEOUT_SETTING) UUIDs(org.opensearch.common.UUIDs) HttpTransportOptions(com.google.cloud.http.HttpTransportOptions) FakeOAuth2HttpHandler(fixture.gcs.FakeOAuth2HttpHandler) InputStreamIndexInput(org.opensearch.common.lucene.store.InputStreamIndexInput) GoogleCloudStorageHttpHandler.getContentRangeStart(fixture.gcs.GoogleCloudStorageHttpHandler.getContentRangeStart) UTF_8(java.nio.charset.StandardCharsets.UTF_8) RestUtils(org.opensearch.rest.RestUtils) IOException(java.io.IOException) TestUtils.createServiceAccount(org.opensearch.repositories.gcs.TestUtils.createServiceAccount) GoogleCloudStorageHttpHandler.getContentRangeLimit(fixture.gcs.GoogleCloudStorageHttpHandler.getContentRangeLimit) ENDPOINT_SETTING(org.opensearch.repositories.gcs.GoogleCloudStorageClientSettings.ENDPOINT_SETTING) CREDENTIALS_FILE_SETTING(org.opensearch.repositories.gcs.GoogleCloudStorageClientSettings.CREDENTIALS_FILE_SETTING) BlobPath(org.opensearch.common.blobstore.BlobPath) ByteArrayIndexInput(org.opensearch.common.lucene.store.ByteArrayIndexInput) StorageException(com.google.cloud.storage.StorageException) HttpHandler(com.sun.net.httpserver.HttpHandler) InputStream(java.io.InputStream) OpenSearchBlobStoreRepositoryIntegTestCase.randomBytes(org.opensearch.repositories.blobstore.OpenSearchBlobStoreRepositoryIntegTestCase.randomBytes) BytesReference(org.opensearch.common.bytes.BytesReference) Optional(java.util.Optional) InputStream(java.io.InputStream) BlobContainer(org.opensearch.common.blobstore.BlobContainer) InputStreamIndexInput(org.opensearch.common.lucene.store.InputStreamIndexInput) Matchers.containsString(org.hamcrest.Matchers.containsString) ByteArrayIndexInput(org.opensearch.common.lucene.store.ByteArrayIndexInput) CountDown(org.opensearch.common.util.concurrent.CountDown)

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