public Connection borrowConnection(long timeout, TimeUnit unit) throws ConnectionException, TimeoutException { if (isShutdown.get()) // Note: throwing a ConnectionException is probably fine in practice as it will trigger the // creation of a new host. // That being said, maybe having a specific exception could be cleaner. throw new ConnectionException(host.getAddress(), "Pool is shutdown"); if (connections.isEmpty()) { for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++) { // We don't respect MAX_SIMULTANEOUS_CREATION here because it's only to // protect against creating connection in excess of core too quickly scheduledForCreation.incrementAndGet(); manager.executor().submit(newConnectionTask); } Connection c = waitForConnection(timeout, unit); c.setKeyspace(manager.poolsState.keyspace); return c; } int minInFlight = Integer.MAX_VALUE; Connection leastBusy = null; for (Connection connection : connections) { int inFlight = connection.inFlight.get(); if (inFlight < minInFlight) { minInFlight = inFlight; leastBusy = connection; } } if (minInFlight >= options().getMaxSimultaneousRequestsPerConnectionThreshold(hostDistance) && connections.size() < options().getMaxConnectionsPerHost(hostDistance)) maybeSpawnNewConnection(); while (true) { int inFlight = leastBusy.inFlight.get(); if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) { leastBusy = waitForConnection(timeout, unit); break; } if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) break; } leastBusy.setKeyspace(manager.poolsState.keyspace); return leastBusy; }
public void returnConnection(Connection connection) { int inFlight = connection.inFlight.decrementAndGet(); if (connection.isDefunct()) { if (host.getMonitor().signalConnectionFailure(connection.lastException())) shutdown(); else replace(connection); } else { if (trash.contains(connection) && inFlight == 0) { if (trash.remove(connection)) close(connection); return; } if (connections.size() > options().getCoreConnectionsPerHost(hostDistance) && inFlight <= options().getMinSimultaneousRequestsPerConnectionThreshold(hostDistance)) { trashConnection(connection); } else { signalAvailableConnection(); } } }
private boolean addConnectionIfUnderMaximum() { // First, make sure we don't cross the allowed limit of open connections for (; ; ) { int opened = open.get(); if (opened >= options().getMaxConnectionsPerHost(hostDistance)) return false; if (open.compareAndSet(opened, opened + 1)) break; } if (isShutdown()) { open.decrementAndGet(); return false; } // Now really open the connection try { connections.add(manager.connectionFactory().open(host)); signalAvailableConnection(); return true; } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Skip the open but ignore otherwise open.decrementAndGet(); return false; } catch (ConnectionException e) { open.decrementAndGet(); logger.debug("Connection error to {} while creating additional connection", host); if (host.getMonitor().signalConnectionFailure(e)) shutdown(); return false; } catch (AuthenticationException e) { // This shouldn't really happen in theory open.decrementAndGet(); logger.error( "Authentication error while creating additional connection (error is: {})", e.getMessage()); shutdown(); return false; } }
private Connection waitForConnection(long timeout, TimeUnit unit) throws ConnectionException, TimeoutException { long start = System.nanoTime(); long remaining = timeout; do { try { awaitAvailableConnection(remaining, unit); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // If we're interrupted fine, check if there is a connection available but stop waiting // otherwise timeout = 0; // this will make us stop the loop if we don't get a connection right away } if (isShutdown()) throw new ConnectionException(host.getAddress(), "Pool is shutdown"); int minInFlight = Integer.MAX_VALUE; Connection leastBusy = null; for (Connection connection : connections) { int inFlight = connection.inFlight.get(); if (inFlight < minInFlight) { minInFlight = inFlight; leastBusy = connection; } } while (true) { int inFlight = leastBusy.inFlight.get(); if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) break; if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) return leastBusy; } remaining = timeout - Cluster.timeSince(start, unit); } while (remaining > 0); throw new TimeoutException(); }