Exemplo n.º 1
0
    private ListenableFuture<Void> queryNextPage(
        ByteBuffer nextStart, final SettableFuture<Void> future) {

      assert !(statement instanceof BatchStatement);

      final Message.Request request = session.makeRequestMessage(statement, nextStart);
      session.execute(
          new RequestHandler.Callback() {

            @Override
            public Message.Request request() {
              return request;
            }

            @Override
            public void register(RequestHandler handler) {}

            @Override
            public void onSet(
                Connection connection,
                Message.Response response,
                ExecutionInfo info,
                Statement statement,
                long latency) {
              try {
                switch (response.type) {
                  case RESULT:
                    Responses.Result rm = (Responses.Result) response;
                    info = update(info, rm, MultiPage.this.session);
                    if (rm.kind == Responses.Result.Kind.ROWS) {
                      Responses.Result.Rows rows = (Responses.Result.Rows) rm;
                      if (rows.metadata.pagingState != null)
                        info =
                            info.withPagingState(rows.metadata.pagingState, protocolVersion)
                                .withStatement(statement);
                      MultiPage.this.nextPages.offer(rows.data);
                      MultiPage.this.fetchState =
                          rows.metadata.pagingState == null
                              ? null
                              : new FetchingState(rows.metadata.pagingState, null);
                    } else if (rm.kind == Responses.Result.Kind.VOID) {
                      // We shouldn't really get a VOID message here but well, no harm in handling
                      // it I suppose
                      MultiPage.this.fetchState = null;
                    } else {
                      logger.error(
                          "Received unknown result type '{}' during paging: ignoring message",
                          rm.kind);
                      // This mean we have probably have a bad node, so defunct the connection
                      connection.defunct(
                          new ConnectionException(
                              connection.address,
                              String.format("Got unexpected %s result response", rm.kind)));
                      future.setException(
                          new DriverInternalError(
                              String.format(
                                  "Got unexpected %s result response from %s",
                                  rm.kind, connection.address)));
                      return;
                    }

                    MultiPage.this.infos.offer(info);
                    future.set(null);
                    break;
                  case ERROR:
                    future.setException(
                        ((Responses.Error) response).asException(connection.address));
                    break;
                  default:
                    // This mean we have probably have a bad node, so defunct the connection
                    connection.defunct(
                        new ConnectionException(
                            connection.address,
                            String.format("Got unexpected %s response", response.type)));
                    future.setException(
                        new DriverInternalError(
                            String.format(
                                "Got unexpected %s response from %s",
                                response.type, connection.address)));
                    break;
                }
              } catch (RuntimeException e) {
                // If we get a bug here, the client will not get it, so better forwarding the error
                future.setException(
                    new DriverInternalError(
                        "Unexpected error while processing response from " + connection.address,
                        e));
              }
            }

            // This is only called for internal calls, so don't bother with ExecutionInfo
            @Override
            public void onSet(
                Connection connection, Message.Response response, long latency, int retryCount) {
              onSet(connection, response, null, null, latency);
            }

            @Override
            public void onException(
                Connection connection, Exception exception, long latency, int retryCount) {
              future.setException(exception);
            }

            @Override
            public boolean onTimeout(Connection connection, long latency, int retryCount) {
              // This won't be called directly since this will be wrapped by RequestHandler.
              throw new UnsupportedOperationException();
            }

            @Override
            public int retryCount() {
              // This is only called for internal calls (i.e, when the callback is not wrapped in
              // RequestHandler).
              // There is no retry logic in that case, so the value does not really matter.
              return 0;
            }
          },
          statement);

      return future;
    }