Bret McGuire created CASSANDRA-19468:
----------------------------------------

             Summary: In some situations 
MetadataManager.SingleThreaded.startSchemaRequest could fail to set 
CompletableFuture arg
                 Key: CASSANDRA-19468
                 URL: https://issues.apache.org/jira/browse/CASSANDRA-19468
             Project: Cassandra
          Issue Type: Bug
          Components: Client/java-driver
            Reporter: Bret McGuire
            Assignee: Henry Hughes


Relevant code is:

 

 
{code:java}
private void startSchemaRequest(CompletableFuture<RefreshSchemaResult> 
refreshFuture) {
  assert adminExecutor.inEventLoop();
  if (closeWasCalled) {
    refreshFuture.complete(new RefreshSchemaResult(metadata));
    return;
  }
  if (currentSchemaRefresh == null) {
    currentSchemaRefresh = refreshFuture;
    LOG.debug("[{}] Starting schema refresh", logPrefix);
    initControlConnectionForSchema()
        .thenCompose(v -> context.getTopologyMonitor().checkSchemaAgreement())
        .whenComplete(
            (schemaInAgreement, agreementError) -> {
              if (agreementError != null) {
                refreshFuture.completeExceptionally(agreementError);
              } else {
                schemaQueriesFactory
                    .newInstance()
                    .execute()
                    .thenApplyAsync(this::parseAndApplySchemaRows, 
adminExecutor)
                    .whenComplete(
                        (newMetadata, metadataError) -> {
                          if (metadataError != null) {
                            refreshFuture.completeExceptionally(metadataError);
                          } else {
                            refreshFuture.complete(
                                new RefreshSchemaResult(newMetadata, 
schemaInAgreement));
                          }

...{code}
 

 

Problem is that the default impl of SchemaQueriesFactory 
(DefaultSchemaQueriesFactory) can chuck exceptions in a few cases, most notably 
if the control connection is in a bad way:

 

 
{code:java}
@Override
public SchemaQueries newInstance() {
  DriverChannel channel = context.getControlConnection().channel();
  if (channel == null || channel.closeFuture().isDone()) {
    throw new IllegalStateException("Control channel not available, aborting 
schema refresh");
  }
  Node node =
      context
          .getMetadataManager()
          .getMetadata()
          .findNode(channel.getEndPoint())
          .orElseThrow(
              () ->
                  new IllegalStateException(
                      "Could not find control node metadata "
                          + channel.getEndPoint()
                          + ", aborting schema refresh"));
  return newInstance(node, channel);
} {code}
 

 

 

In this case the MetadataManager code above will exit out before it ever sets a 
state on refreshFuture... meaning anything waiting on that future will just 
continue to wait.

 

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to