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; }