use of org.opensearch.common.util.CancellableThreads in project OpenSearch by opensearch-project.
the class SeedHostsResolver method resolveHostsLists.
/**
* Resolves a list of hosts to a list of transport addresses. Each host is resolved into a transport address (or a collection of
* addresses if the number of ports is greater than one). Host lookups are done in parallel using specified executor service up
* to the specified resolve timeout.
*
* @param executorService the executor service used to parallelize hostname lookups
* @param logger logger used for logging messages regarding hostname lookups
* @param hosts the hosts to resolve
* @param transportService the transport service
* @param resolveTimeout the timeout before returning from hostname lookups
* @return a list of resolved transport addresses
*/
public static List<TransportAddress> resolveHostsLists(final CancellableThreads cancellableThreads, final ExecutorService executorService, final Logger logger, final List<String> hosts, final TransportService transportService, final TimeValue resolveTimeout) {
Objects.requireNonNull(executorService);
Objects.requireNonNull(logger);
Objects.requireNonNull(hosts);
Objects.requireNonNull(transportService);
Objects.requireNonNull(resolveTimeout);
if (resolveTimeout.nanos() < 0) {
throw new IllegalArgumentException("resolve timeout must be non-negative but was [" + resolveTimeout + "]");
}
// create tasks to submit to the executor service; we will wait up to resolveTimeout for these tasks to complete
final List<Callable<TransportAddress[]>> callables = hosts.stream().map(hn -> (Callable<TransportAddress[]>) () -> transportService.addressesFromString(hn)).collect(Collectors.toList());
final SetOnce<List<Future<TransportAddress[]>>> futures = new SetOnce<>();
try {
cancellableThreads.execute(() -> futures.set(executorService.invokeAll(callables, resolveTimeout.nanos(), TimeUnit.NANOSECONDS)));
} catch (CancellableThreads.ExecutionCancelledException e) {
return Collections.emptyList();
}
final List<TransportAddress> transportAddresses = new ArrayList<>();
final Set<TransportAddress> localAddresses = new HashSet<>();
localAddresses.add(transportService.boundAddress().publishAddress());
localAddresses.addAll(Arrays.asList(transportService.boundAddress().boundAddresses()));
// ExecutorService#invokeAll guarantees that the futures are returned in the iteration order of the tasks so we can associate the
// hostname with the corresponding task by iterating together
final Iterator<String> it = hosts.iterator();
for (final Future<TransportAddress[]> future : futures.get()) {
assert future.isDone();
final String hostname = it.next();
if (!future.isCancelled()) {
try {
final TransportAddress[] addresses = future.get();
logger.trace("resolved host [{}] to {}", hostname, addresses);
for (int addressId = 0; addressId < addresses.length; addressId++) {
final TransportAddress address = addresses[addressId];
// no point in pinging ourselves
if (localAddresses.contains(address) == false) {
transportAddresses.add(address);
}
}
} catch (final ExecutionException e) {
assert e.getCause() != null;
final String message = "failed to resolve host [" + hostname + "]";
logger.warn(message, e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// ignore
}
} else {
logger.warn("timed out after [{}] resolving host [{}]", resolveTimeout, hostname);
}
}
return Collections.unmodifiableList(transportAddresses);
}
use of org.opensearch.common.util.CancellableThreads in project OpenSearch by opensearch-project.
the class PeerRecoveryTargetService method doRecovery.
private void doRecovery(final long recoveryId, final StartRecoveryRequest preExistingRequest) {
final String actionName;
final TransportRequest requestToSend;
final StartRecoveryRequest startRequest;
final RecoveryState.Timer timer;
CancellableThreads cancellableThreads;
try (RecoveryRef recoveryRef = onGoingRecoveries.getRecovery(recoveryId)) {
if (recoveryRef == null) {
logger.trace("not running recovery with id [{}] - can not find it (probably finished)", recoveryId);
return;
}
final RecoveryTarget recoveryTarget = recoveryRef.target();
timer = recoveryTarget.state().getTimer();
cancellableThreads = recoveryTarget.cancellableThreads();
if (preExistingRequest == null) {
try {
final IndexShard indexShard = recoveryTarget.indexShard();
indexShard.preRecovery();
assert recoveryTarget.sourceNode() != null : "can not do a recovery without a source node";
logger.trace("{} preparing shard for peer recovery", recoveryTarget.shardId());
indexShard.prepareForIndexRecovery();
final long startingSeqNo = indexShard.recoverLocallyUpToGlobalCheckpoint();
assert startingSeqNo == UNASSIGNED_SEQ_NO || recoveryTarget.state().getStage() == RecoveryState.Stage.TRANSLOG : "unexpected recovery stage [" + recoveryTarget.state().getStage() + "] starting seqno [ " + startingSeqNo + "]";
startRequest = getStartRecoveryRequest(logger, clusterService.localNode(), recoveryTarget, startingSeqNo);
requestToSend = startRequest;
actionName = PeerRecoverySourceService.Actions.START_RECOVERY;
} catch (final Exception e) {
// this will be logged as warning later on...
logger.trace("unexpected error while preparing shard for peer recovery, failing recovery", e);
onGoingRecoveries.failRecovery(recoveryId, new RecoveryFailedException(recoveryTarget.state(), "failed to prepare shard for recovery", e), true);
return;
}
logger.trace("{} starting recovery from {}", startRequest.shardId(), startRequest.sourceNode());
} else {
startRequest = preExistingRequest;
requestToSend = new ReestablishRecoveryRequest(recoveryId, startRequest.shardId(), startRequest.targetAllocationId());
actionName = PeerRecoverySourceService.Actions.REESTABLISH_RECOVERY;
logger.trace("{} reestablishing recovery from {}", startRequest.shardId(), startRequest.sourceNode());
}
}
RecoveryResponseHandler responseHandler = new RecoveryResponseHandler(startRequest, timer);
try {
cancellableThreads.executeIO(() -> transportService.sendRequest(startRequest.sourceNode(), actionName, requestToSend, responseHandler));
} catch (CancellableThreads.ExecutionCancelledException e) {
logger.trace("recovery cancelled", e);
} catch (Exception e) {
responseHandler.onException(e);
}
}
use of org.opensearch.common.util.CancellableThreads in project OpenSearch by opensearch-project.
the class FileBasedSeedHostsProviderTests method setupAndRunHostProvider.
// sets up the config dir, writes to the unicast hosts file in the config dir,
// and then runs the file-based unicast host provider to get the list of discovery nodes
private List<TransportAddress> setupAndRunHostProvider(final List<String> hostEntries) throws IOException {
final Path homeDir = createTempDir();
final Path configPath = randomBoolean() ? homeDir.resolve("config") : createTempDir();
Files.createDirectories(configPath);
try (BufferedWriter writer = Files.newBufferedWriter(configPath.resolve(UNICAST_HOSTS_FILE))) {
writer.write(String.join("\n", hostEntries));
}
return new FileBasedSeedHostsProvider(configPath).getSeedAddresses(hosts -> SeedHostsResolver.resolveHostsLists(new CancellableThreads(), executorService, logger, hosts, transportService, TimeValue.timeValueSeconds(10)));
}
use of org.opensearch.common.util.CancellableThreads in project OpenSearch by opensearch-project.
the class SeedHostsResolverTests method testUnknownHost.
public void testUnknownHost() {
final Logger logger = mock(Logger.class);
final NetworkService networkService = new NetworkService(Collections.emptyList());
final String hostname = randomAlphaOfLength(8);
final UnknownHostException unknownHostException = new UnknownHostException(hostname);
final Transport transport = new MockNioTransport(Settings.EMPTY, Version.CURRENT, threadPool, networkService, PageCacheRecycler.NON_RECYCLING_INSTANCE, new NamedWriteableRegistry(Collections.emptyList()), new NoneCircuitBreakerService()) {
@Override
public BoundTransportAddress boundAddress() {
return new BoundTransportAddress(new TransportAddress[] { new TransportAddress(InetAddress.getLoopbackAddress(), 9300) }, new TransportAddress(InetAddress.getLoopbackAddress(), 9300));
}
@Override
public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
throw unknownHostException;
}
};
closeables.push(transport);
final TransportService transportService = new TransportService(Settings.EMPTY, transport, threadPool, TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
closeables.push(transportService);
final List<TransportAddress> transportAddresses = SeedHostsResolver.resolveHostsLists(new CancellableThreads(), executorService, logger, Arrays.asList(hostname), transportService, TimeValue.timeValueSeconds(30));
assertThat(transportAddresses, empty());
verify(logger).warn("failed to resolve host [" + hostname + "]", unknownHostException);
}
use of org.opensearch.common.util.CancellableThreads in project OpenSearch by opensearch-project.
the class SeedHostsResolverTests method testInvalidHosts.
public void testInvalidHosts() throws IllegalAccessException {
final Logger logger = mock(Logger.class);
final Transport transport = new MockNioTransport(Settings.EMPTY, Version.CURRENT, threadPool, new NetworkService(Collections.emptyList()), PageCacheRecycler.NON_RECYCLING_INSTANCE, new NamedWriteableRegistry(Collections.emptyList()), new NoneCircuitBreakerService()) {
@Override
public BoundTransportAddress boundAddress() {
return new BoundTransportAddress(new TransportAddress[] { new TransportAddress(InetAddress.getLoopbackAddress(), 9300) }, new TransportAddress(InetAddress.getLoopbackAddress(), 9300));
}
};
closeables.push(transport);
final TransportService transportService = new TransportService(Settings.EMPTY, transport, threadPool, TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
closeables.push(transportService);
final List<TransportAddress> transportAddresses = SeedHostsResolver.resolveHostsLists(new CancellableThreads(), executorService, logger, Arrays.asList("127.0.0.1:9300:9300", "127.0.0.1:9301"), transportService, TimeValue.timeValueSeconds(30));
// only one of the two is valid and will be used
assertThat(transportAddresses, hasSize(1));
assertThat(transportAddresses.get(0).getAddress(), equalTo("127.0.0.1"));
assertThat(transportAddresses.get(0).getPort(), equalTo(9301));
verify(logger).warn(eq("failed to resolve host [127.0.0.1:9300:9300]"), Mockito.any(IllegalArgumentException.class));
}
Aggregations