Source:
<code>ListenableFuture<Connection> setKeyspaceAsync(final String keyspace) throws ConnectionException, BusyConnectionException { if (Objects.equal(this.keyspace, keyspace)) { return thisFuture; } SetKeyspaceAttempt attempt = new SetKeyspaceAttempt(keyspace); while (true) { SetKeyspaceAttempt existingAttempt = targetKeyspace.get(); if (attempt.equals(existingAttempt)) { attempt = existingAttempt; break; <START> } else if (targetKeyspace.compareAndSet(existingAttempt, attempt)) { <END> if (existingAttempt != null && !existingAttempt.future.isDone()) { logger.debug("{} There is already an in progress attempt to set keyspace on this connection for keyspace '{}', beginning set keyspace for '{}'", this, existingAttempt.keyspace, keyspace); } logger.debug("{} Setting keyspace {}", this, keyspace); final SettableFuture<Connection> ksFuture = attempt.future; Future future = write(new Requests.Query("USE \"" + keyspace + '"')); Futures.addCallback(future, new FutureCallback<Message.Response>() { @Override public void onSuccess(Message.Response response) { if (response instanceof SetKeyspace) { Connection.this.keyspace = ((SetKeyspace) response).keyspace; logger.debug("{} Keyspace set to {}", Connection.this, keyspace); ksFuture.set(Connection.this); } else if (response.type == ERROR) { Responses.Error error = (Responses.Error) response; ksFuture.setException(defunct(error.asException(address))); } else { ksFuture.setException(defunct(new DriverInternalError("Unexpected response while setting keyspace: " + response))); } } @Override public void onFailure(Throwable t) { ksFuture.setException(t); } }, factory.manager.configuration.getPoolingOptions().getInitializationExecutor()); break; } } return attempt.future; }</code><technical_language>I agree, if CAS fails, new attempt is for keyspace, in case next iteration of while loop new existingAttempt keyspace set (line 501-502). clear equals() SetKeyspaceAttempt is keyspace (maybe I compare keyspaces of attempts is more clear?) If CAS succeeds existingAttempt is for a keyspace, I ok. I added a debug statement (at 508) if existingAttempt is in flight, this some requests fail keyspace is changing, is do that. change logging statement warning a user this is happening, wdyt</technical_language>

Target:
ListenableFuture<Connection> setKeyspaceAsync(final String keyspace) throws ConnectionException, BusyConnectionException { SetKeyspaceAttempt existingAttempt = targetKeyspace.get(); if (Objects.equal(existingAttempt.keyspace, keyspace)) return existingAttempt.future; final SettableFuture<Connection> ksFuture = SettableFuture.create(); final SetKeyspaceAttempt attempt = new SetKeyspaceAttempt(keyspace, ksFuture); while (true) { existingAttempt = targetKeyspace.get(); if (attempt.equals(existingAttempt)) { return existingAttempt.future; } else if (!existingAttempt.future.isDone()) { ksFuture.setException(new DriverException("Aborting attempt to set keyspace to '" + keyspace + "' since there is already an in flight attempt to set keyspace to '" + existingAttempt.keyspace + "'. " + "This can happen if you try to USE different keyspaces from the same session simultaneously.")); return ksFuture; } else if (targetKeyspace.compareAndSet(existingAttempt, attempt)) { logger.debug("{} Setting keyspace {}", this, keyspace); Future future = write(new Requests.Query("USE \"" + keyspace + '"')); Futures.addCallback(future, new FutureCallback<Message.Response>() { @Override public void onSuccess(Message.Response response) { if (response instanceof SetKeyspace) { logger.debug("{} Keyspace set to {}", Connection.this, keyspace); ksFuture.set(Connection.this); } else { targetKeyspace.compareAndSet(attempt, defaultKeyspaceAttempt); if (response.type == ERROR) { Responses.Error error = (Responses.Error) response; ksFuture.setException(defunct(error.asException(address))); } else { ksFuture.setException(defunct(new DriverInternalError("Unexpected response while setting keyspace: " + response))); } } } @Override public void onFailure(Throwable t) { targetKeyspace.compareAndSet(attempt, defaultKeyspaceAttempt); ksFuture.setException(t); } }, factory.manager.configuration.getPoolingOptions().getInitializationExecutor()); return ksFuture; } } }