Search in sources :

Example 21 with Releasable

use of org.elasticsearch.common.lease.Releasable in project elasticsearch by elastic.

the class InternalEngine method innerDelete.

private DeleteResult innerDelete(Delete delete) throws IOException {
    assert assertSequenceNumber(delete.origin(), delete.seqNo());
    final Translog.Location location;
    final long updatedVersion;
    final boolean found;
    long seqNo = delete.seqNo();
    try (Releasable ignored = acquireLock(delete.uid())) {
        lastWriteNanos = delete.startTime();
        final long currentVersion;
        final boolean deleted;
        final VersionValue versionValue = versionMap.getUnderLock(delete.uid());
        assert incrementVersionLookup();
        if (versionValue == null) {
            currentVersion = loadCurrentVersionFromIndex(delete.uid());
            deleted = currentVersion == Versions.NOT_FOUND;
        } else {
            currentVersion = checkDeletedAndGCed(versionValue);
            deleted = versionValue.delete();
        }
        final long expectedVersion = delete.version();
        Optional<DeleteResult> resultOnVersionConflict;
        try {
            final boolean isVersionConflict = checkVersionConflict(delete, currentVersion, expectedVersion, deleted);
            resultOnVersionConflict = isVersionConflict ? Optional.of(new DeleteResult(expectedVersion, delete.seqNo(), true)) : Optional.empty();
        } catch (IllegalArgumentException | VersionConflictEngineException ex) {
            resultOnVersionConflict = Optional.of(new DeleteResult(ex, expectedVersion, delete.seqNo()));
        }
        final DeleteResult deleteResult;
        if (resultOnVersionConflict.isPresent()) {
            deleteResult = resultOnVersionConflict.get();
        } else {
            if (delete.origin() == Operation.Origin.PRIMARY) {
                seqNo = seqNoService().generateSeqNo();
            }
            updatedVersion = delete.versionType().updateVersion(currentVersion, expectedVersion);
            found = deleteIfFound(delete.uid(), currentVersion, deleted, versionValue);
            deleteResult = new DeleteResult(updatedVersion, seqNo, found);
            versionMap.putUnderLock(delete.uid().bytes(), new DeleteVersionValue(updatedVersion, engineConfig.getThreadPool().relativeTimeInMillis()));
        }
        if (!deleteResult.hasFailure()) {
            location = delete.origin() != Operation.Origin.LOCAL_TRANSLOG_RECOVERY ? translog.add(new Translog.Delete(delete, deleteResult)) : null;
            deleteResult.setTranslogLocation(location);
        }
        deleteResult.setTook(System.nanoTime() - delete.startTime());
        deleteResult.freeze();
        return deleteResult;
    } finally {
        if (seqNo != SequenceNumbersService.UNASSIGNED_SEQ_NO) {
            seqNoService().markSeqNoAsCompleted(seqNo);
        }
    }
}
Also used : Translog(org.elasticsearch.index.translog.Translog) Releasable(org.elasticsearch.common.lease.Releasable)

Example 22 with Releasable

use of org.elasticsearch.common.lease.Releasable in project elasticsearch by elastic.

the class TcpTransport method sendResponse.

private void sendResponse(Version nodeVersion, Channel channel, final TransportResponse response, final long requestId, final String action, TransportResponseOptions options, byte status) throws IOException {
    if (compress) {
        options = TransportResponseOptions.builder(options).withCompress(true).build();
    }
    // TODO share some code with sendRequest
    status = TransportStatus.setResponse(status);
    ReleasableBytesStreamOutput bStream = new ReleasableBytesStreamOutput(bigArrays);
    // we wrap this in a release once since if the onRequestSent callback throws an exception
    // we might release things twice and this should be prevented
    final Releasable toRelease = Releasables.releaseOnce(() -> Releasables.close(bStream.bytes()));
    boolean addedReleaseListener = false;
    StreamOutput stream = bStream;
    try {
        if (options.compress()) {
            status = TransportStatus.setCompress(status);
            stream = CompressorFactory.COMPRESSOR.streamOutput(stream);
        }
        threadPool.getThreadContext().writeTo(stream);
        stream.setVersion(nodeVersion);
        BytesReference reference = buildMessage(requestId, status, nodeVersion, response, stream, bStream);
        final TransportResponseOptions finalOptions = options;
        Runnable onRequestSent = () -> {
            // this might be called in a different thread
            try {
                toRelease.close();
            } finally {
                transportServiceAdapter.onResponseSent(requestId, action, response, finalOptions);
            }
        };
        addedReleaseListener = internalSendMessage(channel, reference, onRequestSent);
    } finally {
        try {
            IOUtils.close(stream);
        } finally {
            if (!addedReleaseListener) {
                toRelease.close();
            }
        }
    }
}
Also used : BytesReference(org.elasticsearch.common.bytes.BytesReference) CompositeBytesReference(org.elasticsearch.common.bytes.CompositeBytesReference) AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) AbstractLifecycleRunnable(org.elasticsearch.common.util.concurrent.AbstractLifecycleRunnable) ReleasableBytesStreamOutput(org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput) Releasable(org.elasticsearch.common.lease.Releasable) StreamOutput(org.elasticsearch.common.io.stream.StreamOutput) ReleasableBytesStreamOutput(org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput) BytesStreamOutput(org.elasticsearch.common.io.stream.BytesStreamOutput)

Example 23 with Releasable

use of org.elasticsearch.common.lease.Releasable in project elasticsearch by elastic.

the class Netty4HttpChannel method sendResponse.

@Override
public void sendResponse(RestResponse response) {
    // if the response object was created upstream, then use it;
    // otherwise, create a new one
    ByteBuf buffer = Netty4Utils.toByteBuf(response.content());
    final FullHttpResponse resp;
    if (HttpMethod.HEAD.equals(nettyRequest.method())) {
        resp = newResponse(Unpooled.EMPTY_BUFFER);
    } else {
        resp = newResponse(buffer);
    }
    resp.setStatus(getStatus(response.status()));
    Netty4CorsHandler.setCorsResponseHeaders(nettyRequest, resp, transport.getCorsConfig());
    String opaque = nettyRequest.headers().get("X-Opaque-Id");
    if (opaque != null) {
        setHeaderField(resp, "X-Opaque-Id", opaque);
    }
    // Add all custom headers
    addCustomHeaders(resp, response.getHeaders());
    addCustomHeaders(resp, threadContext.getResponseHeaders());
    BytesReference content = response.content();
    boolean release = content instanceof Releasable;
    try {
        // If our response doesn't specify a content-type header, set one
        setHeaderField(resp, HttpHeaderNames.CONTENT_TYPE.toString(), response.contentType(), false);
        // If our response has no content-length, calculate and set one
        setHeaderField(resp, HttpHeaderNames.CONTENT_LENGTH.toString(), String.valueOf(buffer.readableBytes()), false);
        addCookies(resp);
        final ChannelPromise promise = channel.newPromise();
        if (release) {
            promise.addListener(f -> ((Releasable) content).close());
        }
        if (isCloseConnection()) {
            promise.addListener(ChannelFutureListener.CLOSE);
        }
        final Object msg;
        if (pipelinedRequest != null) {
            msg = pipelinedRequest.createHttpResponse(resp, promise);
        } else {
            msg = resp;
        }
        channel.writeAndFlush(msg, promise);
        release = false;
    } finally {
        if (release) {
            ((Releasable) content).close();
        }
        if (pipelinedRequest != null) {
            pipelinedRequest.release();
        }
    }
}
Also used : BytesReference(org.elasticsearch.common.bytes.BytesReference) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) Releasable(org.elasticsearch.common.lease.Releasable) ChannelPromise(io.netty.channel.ChannelPromise) ByteBuf(io.netty.buffer.ByteBuf)

Example 24 with Releasable

use of org.elasticsearch.common.lease.Releasable in project elasticsearch by elastic.

the class IndexShardTests method testLockingBeforeAndAfterRelocated.

public void testLockingBeforeAndAfterRelocated() throws Exception {
    final IndexShard shard = newStartedShard(true);
    shard.updateRoutingEntry(ShardRoutingHelper.relocate(shard.routingEntry(), "other_node"));
    CountDownLatch latch = new CountDownLatch(1);
    Thread recoveryThread = new Thread(() -> {
        latch.countDown();
        try {
            shard.relocated("simulated recovery");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });
    try (Releasable ignored = acquirePrimaryOperationLockBlockingly(shard)) {
        // start finalization of recovery
        recoveryThread.start();
        latch.await();
        // recovery can only be finalized after we release the current primaryOperationLock
        assertThat(shard.state(), equalTo(IndexShardState.STARTED));
    }
    // recovery can be now finalized
    recoveryThread.join();
    assertThat(shard.state(), equalTo(IndexShardState.RELOCATED));
    try (Releasable ignored = acquirePrimaryOperationLockBlockingly(shard)) {
        // lock can again be acquired
        assertThat(shard.state(), equalTo(IndexShardState.RELOCATED));
    }
    closeShards(shard);
}
Also used : Releasable(org.elasticsearch.common.lease.Releasable) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 25 with Releasable

use of org.elasticsearch.common.lease.Releasable in project elasticsearch by elastic.

the class IndexShardTests method testStressRelocated.

public void testStressRelocated() throws Exception {
    final IndexShard shard = newStartedShard(true);
    shard.updateRoutingEntry(ShardRoutingHelper.relocate(shard.routingEntry(), "other_node"));
    final int numThreads = randomIntBetween(2, 4);
    Thread[] indexThreads = new Thread[numThreads];
    CountDownLatch allPrimaryOperationLocksAcquired = new CountDownLatch(numThreads);
    CyclicBarrier barrier = new CyclicBarrier(numThreads + 1);
    for (int i = 0; i < indexThreads.length; i++) {
        indexThreads[i] = new Thread() {

            @Override
            public void run() {
                try (Releasable operationLock = acquirePrimaryOperationLockBlockingly(shard)) {
                    allPrimaryOperationLocksAcquired.countDown();
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException | ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        indexThreads[i].start();
    }
    AtomicBoolean relocated = new AtomicBoolean();
    final Thread recoveryThread = new Thread(() -> {
        try {
            shard.relocated("simulated recovery");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        relocated.set(true);
    });
    // ensure we wait for all primary operation locks to be acquired
    allPrimaryOperationLocksAcquired.await();
    // start recovery thread
    recoveryThread.start();
    assertThat(relocated.get(), equalTo(false));
    assertThat(shard.getActiveOperationsCount(), greaterThan(0));
    // ensure we only transition to RELOCATED state after pending operations completed
    assertThat(shard.state(), equalTo(IndexShardState.STARTED));
    // complete pending operations
    barrier.await();
    // complete recovery/relocation
    recoveryThread.join();
    // ensure relocated successfully once pending operations are done
    assertThat(relocated.get(), equalTo(true));
    assertThat(shard.state(), equalTo(IndexShardState.RELOCATED));
    assertThat(shard.getActiveOperationsCount(), equalTo(0));
    for (Thread indexThread : indexThreads) {
        indexThread.join();
    }
    closeShards(shard);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Releasable(org.elasticsearch.common.lease.Releasable) CountDownLatch(java.util.concurrent.CountDownLatch) CyclicBarrier(java.util.concurrent.CyclicBarrier)

Aggregations

Releasable (org.elasticsearch.common.lease.Releasable)38 PlainActionFuture (org.elasticsearch.action.support.PlainActionFuture)7 IndexShard (org.elasticsearch.index.shard.IndexShard)7 ClusterState (org.elasticsearch.cluster.ClusterState)6 IOException (java.io.IOException)5 CountDownLatch (java.util.concurrent.CountDownLatch)5 ElasticsearchException (org.elasticsearch.ElasticsearchException)5 ShardRouting (org.elasticsearch.cluster.routing.ShardRouting)5 TestShardRouting (org.elasticsearch.cluster.routing.TestShardRouting)5 Settings (org.elasticsearch.common.settings.Settings)5 ExecutionException (java.util.concurrent.ExecutionException)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)4 BytesReference (org.elasticsearch.common.bytes.BytesReference)4 ArrayList (java.util.ArrayList)3 ActionListener (org.elasticsearch.action.ActionListener)3 ClusterBlockException (org.elasticsearch.cluster.block.ClusterBlockException)3 AbstractRunnable (org.elasticsearch.common.util.concurrent.AbstractRunnable)3 DiscoverySettings (org.elasticsearch.discovery.DiscoverySettings)3 ShardId (org.elasticsearch.index.shard.ShardId)3 List (java.util.List)2