From 4ed593abf617b987ee87ba7d9b0f5a1e7d39ac98 Mon Sep 17 00:00:00 2001 From: Belonogov Nikolay Date: Thu, 16 Nov 2023 16:59:41 +0300 Subject: [PATCH] Fix infinite loop when retrying to get a connection - Fix infinite loop - CHANGELOG.md Closes #440 --- CHANGELOG.md | 1 + ...arantoolConnectionSelectionStrategies.java | 37 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index badb249e5..5eacd0b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bugfixes - Fix Instant converter to parse 8 bytes datetime ([#408](https://github.com/tarantool/cartridge-java/issues/408)) +- Fix infinite loop when retrying to get a connection ([#440](https://github.com/tarantool/cartridge-java/issues/440)) ### Internal and API changes diff --git a/src/main/java/io/tarantool/driver/api/connection/TarantoolConnectionSelectionStrategies.java b/src/main/java/io/tarantool/driver/api/connection/TarantoolConnectionSelectionStrategies.java index 659fda020..7ee840544 100644 --- a/src/main/java/io/tarantool/driver/api/connection/TarantoolConnectionSelectionStrategies.java +++ b/src/main/java/io/tarantool/driver/api/connection/TarantoolConnectionSelectionStrategies.java @@ -38,9 +38,11 @@ static final class RoundRobinStrategy implements ConnectionSelectionStrategy { private final TarantoolConnectionIterator connectionIterator; private final AtomicInteger available; + private final int connectionsCount; RoundRobinStrategy(Collection connections) { - this.available = new AtomicInteger(connections.size()); + this.connectionsCount = connections.size(); + this.available = new AtomicInteger(this.connectionsCount); this.connectionIterator = new TarantoolConnectionIterator(connections.stream() .peek(conn -> conn.addConnectionCloseListener(c -> available.getAndDecrement())) .collect(Collectors.toList())); @@ -48,12 +50,15 @@ static final class RoundRobinStrategy implements ConnectionSelectionStrategy { @Override public TarantoolConnection next() throws NoAvailableConnectionsException { - if (available.get() > 0) { - while (connectionIterator.hasNext()) { - TarantoolConnection connection = connectionIterator.next(); - if (connection.isConnected()) { - return connection; - } + int attempts = 0; + while (available.get() > 0 && connectionIterator.hasNext()) { + TarantoolConnection connection = connectionIterator.next(); + if (connection.isConnected()) { + return connection; + } + + if (++attempts > connectionsCount) { + break; } } throw new NoAvailableConnectionsException(); @@ -84,10 +89,12 @@ static final class ParallelRoundRobinStrategy implements ConnectionSelectionStra private final TarantoolClientConfig config; private final CyclingIterator iteratorsIterator; private final AtomicInteger available; + private final int connectionsCount; ParallelRoundRobinStrategy(TarantoolClientConfig config, Collection connections) { this.config = config; - this.available = new AtomicInteger(connections.size()); + this.connectionsCount = connections.size(); + this.available = new AtomicInteger(this.connectionsCount); this.iteratorsIterator = new CyclingIterator<>(populateIterators(connections)); } @@ -106,12 +113,14 @@ private Collection populateIterators( @Override public TarantoolConnection next() throws NoAvailableConnectionsException { - if (available.get() > 0) { - while (iteratorsIterator.hasNext()) { - TarantoolConnection connection = iteratorsIterator.next().next(); - if (connection.isConnected()) { - return connection; - } + int attempts = 0; + while (available.get() > 0 && iteratorsIterator.hasNext()) { + TarantoolConnection connection = iteratorsIterator.next().next(); + if (connection.isConnected()) { + return connection; + } + if (++attempts > connectionsCount) { + break; } } throw new NoAvailableConnectionsException();