use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class TransportService method sendRequest.
/**
* Sends a request on the specified connection. If there is a failure sending the request, the specified handler is invoked.
*
* @param connection the connection to send the request on
* @param action the name of the action
* @param request the request
* @param options the options for this request
* @param handler the response handler
* @param <T> the type of the transport response
*/
public final <T extends TransportResponse> void sendRequest(final Transport.Connection connection, final String action, final TransportRequest request, final TransportRequestOptions options, final TransportResponseHandler<T> handler) {
try {
final TransportResponseHandler<T> delegate;
if (request.getParentTask().isSet()) {
// TODO: capture the connection instead so that we can cancel child tasks on the remote connections.
final Releasable unregisterChildNode = taskManager.registerChildNode(request.getParentTask().getId(), connection.getNode());
delegate = new TransportResponseHandler<T>() {
@Override
public void handleResponse(T response) {
unregisterChildNode.close();
handler.handleResponse(response);
}
@Override
public void handleException(TransportException exp) {
unregisterChildNode.close();
handler.handleException(exp);
}
@Override
public String executor() {
return handler.executor();
}
@Override
public T read(StreamInput in) throws IOException {
return handler.read(in);
}
@Override
public String toString() {
return getClass().getName() + "/[" + action + "]:" + handler.toString();
}
};
} else {
delegate = handler;
}
asyncSender.sendRequest(connection, action, request, options, delegate);
} catch (final Exception ex) {
// the caller might not handle this so we invoke the handler
final TransportException te;
if (ex instanceof TransportException) {
te = (TransportException) ex;
} else {
te = new TransportException("failure to send", ex);
}
handler.handleException(te);
}
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class InboundMessage method takeBreakerReleaseControl.
public Releasable takeBreakerReleaseControl() {
final Releasable toReturn = breakerRelease;
breakerRelease = null;
if (toReturn != null) {
return toReturn;
} else {
return () -> {
};
}
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class TaskManagerTests method testTrackingChannelTask.
public void testTrackingChannelTask() throws Exception {
final TaskManager taskManager = new TaskManager(Settings.EMPTY, threadPool, Collections.emptySet());
Set<Task> cancelledTasks = ConcurrentCollections.newConcurrentSet();
taskManager.setTaskCancellationService(new TaskCancellationService(mock(TransportService.class)) {
@Override
void cancelTaskAndDescendants(CancellableTask task, String reason, boolean waitForCompletion, ActionListener<Void> listener) {
assertThat(reason, equalTo("channel was closed"));
assertFalse(waitForCompletion);
assertTrue("task [" + task + "] was cancelled already", cancelledTasks.add(task));
}
});
Map<TcpChannel, Set<Task>> pendingTasks = new HashMap<>();
Set<Task> expectedCancelledTasks = new HashSet<>();
FakeTcpChannel[] channels = new FakeTcpChannel[randomIntBetween(1, 10)];
List<Releasable> stopTrackingTasks = new ArrayList<>();
for (int i = 0; i < channels.length; i++) {
channels[i] = new SingleThreadedTcpChannel();
}
int iterations = randomIntBetween(1, 200);
for (int i = 0; i < iterations; i++) {
final List<Releasable> subset = randomSubsetOf(stopTrackingTasks);
stopTrackingTasks.removeAll(subset);
Releasables.close(subset);
final FakeTcpChannel channel = randomFrom(channels);
final Task task = taskManager.register("transport", "test", new CancellableRequest(Integer.toString(i)));
if (channel.isOpen() && randomBoolean()) {
channel.close();
expectedCancelledTasks.addAll(pendingTasks.getOrDefault(channel, Collections.emptySet()));
}
final Releasable stopTracking = taskManager.startTrackingCancellableChannelTask(channel, (CancellableTask) task);
if (channel.isOpen()) {
pendingTasks.computeIfAbsent(channel, k -> new HashSet<>()).add(task);
stopTrackingTasks.add(() -> {
stopTracking.close();
assertTrue(pendingTasks.get(channel).remove(task));
expectedCancelledTasks.remove(task);
});
} else {
expectedCancelledTasks.add(task);
}
}
assertBusy(() -> assertThat(expectedCancelledTasks, everyItem(in(cancelledTasks))), 30, TimeUnit.SECONDS);
for (FakeTcpChannel channel : channels) {
channel.close();
}
assertThat(taskManager.numberOfChannelPendingTaskTrackers(), equalTo(0));
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class InboundPipelineTests method testDecodeExceptionIsPropagated.
public void testDecodeExceptionIsPropagated() throws IOException {
BiConsumer<TcpChannel, InboundMessage> messageHandler = (c, m) -> {
};
final StatsTracker statsTracker = new StatsTracker();
final LongSupplier millisSupplier = () -> TimeValue.nsecToMSec(System.nanoTime());
final InboundDecoder decoder = new InboundDecoder(Version.CURRENT, PageCacheRecycler.NON_RECYCLING_INSTANCE);
final Supplier<CircuitBreaker> breaker = () -> new NoopCircuitBreaker("test");
final InboundAggregator aggregator = new InboundAggregator(breaker, (Predicate<String>) action -> true);
final InboundPipeline pipeline = new InboundPipeline(statsTracker, millisSupplier, decoder, aggregator, messageHandler);
try (BytesStreamOutput streamOutput = new BytesStreamOutput()) {
String actionName = "actionName";
final Version invalidVersion = Version.CURRENT.minimumCompatibilityVersion().minimumCompatibilityVersion();
final String value = randomAlphaOfLength(1000);
final boolean isRequest = randomBoolean();
final long requestId = randomNonNegativeLong();
OutboundMessage message;
if (isRequest) {
message = new OutboundMessage.Request(threadContext, new String[0], new TestRequest(value), invalidVersion, actionName, requestId, false, false);
} else {
message = new OutboundMessage.Response(threadContext, Collections.emptySet(), new TestResponse(value), invalidVersion, requestId, false, false);
}
final BytesReference reference = message.serialize(streamOutput);
try (ReleasableBytesReference releasable = ReleasableBytesReference.wrap(reference)) {
expectThrows(IllegalStateException.class, () -> pipeline.handleBytes(new FakeTcpChannel(), releasable));
}
// Pipeline cannot be reused after uncaught exception
final IllegalStateException ise = expectThrows(IllegalStateException.class, () -> pipeline.handleBytes(new FakeTcpChannel(), ReleasableBytesReference.wrap(BytesArray.EMPTY)));
assertEquals("Pipeline state corrupted by uncaught exception", ise.getMessage());
}
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class InboundPipelineTests method testEnsureBodyIsNotPrematurelyReleased.
public void testEnsureBodyIsNotPrematurelyReleased() throws IOException {
BiConsumer<TcpChannel, InboundMessage> messageHandler = (c, m) -> {
};
final StatsTracker statsTracker = new StatsTracker();
final LongSupplier millisSupplier = () -> TimeValue.nsecToMSec(System.nanoTime());
final InboundDecoder decoder = new InboundDecoder(Version.CURRENT, PageCacheRecycler.NON_RECYCLING_INSTANCE);
final Supplier<CircuitBreaker> breaker = () -> new NoopCircuitBreaker("test");
final InboundAggregator aggregator = new InboundAggregator(breaker, (Predicate<String>) action -> true);
final InboundPipeline pipeline = new InboundPipeline(statsTracker, millisSupplier, decoder, aggregator, messageHandler);
try (BytesStreamOutput streamOutput = new BytesStreamOutput()) {
String actionName = "actionName";
final Version version = Version.CURRENT;
final String value = randomAlphaOfLength(1000);
final boolean isRequest = randomBoolean();
final long requestId = randomNonNegativeLong();
OutboundMessage message;
if (isRequest) {
message = new OutboundMessage.Request(threadContext, new String[0], new TestRequest(value), version, actionName, requestId, false, false);
} else {
message = new OutboundMessage.Response(threadContext, Collections.emptySet(), new TestResponse(value), version, requestId, false, false);
}
final BytesReference reference = message.serialize(streamOutput);
final int fixedHeaderSize = TcpHeader.headerSize(Version.CURRENT);
final int variableHeaderSize = reference.getInt(fixedHeaderSize - 4);
final int totalHeaderSize = fixedHeaderSize + variableHeaderSize;
final AtomicBoolean bodyReleased = new AtomicBoolean(false);
for (int i = 0; i < totalHeaderSize - 1; ++i) {
try (ReleasableBytesReference slice = ReleasableBytesReference.wrap(reference.slice(i, 1))) {
pipeline.handleBytes(new FakeTcpChannel(), slice);
}
}
final Releasable releasable = () -> bodyReleased.set(true);
final int from = totalHeaderSize - 1;
final BytesReference partHeaderPartBody = reference.slice(from, reference.length() - from - 1);
try (ReleasableBytesReference slice = new ReleasableBytesReference(partHeaderPartBody, releasable)) {
pipeline.handleBytes(new FakeTcpChannel(), slice);
}
assertFalse(bodyReleased.get());
try (ReleasableBytesReference slice = new ReleasableBytesReference(reference.slice(reference.length() - 1, 1), releasable)) {
pipeline.handleBytes(new FakeTcpChannel(), slice);
}
assertTrue(bodyReleased.get());
}
}
Aggregations