Example #1
0
  /**
   * Execute the provided query asynchronously.
   *
   * <p>This method does not block. It returns as soon as the query has been successfully sent to a
   * Cassandra node. In particular, returning from this method does not guarantee that the query is
   * valid. Any exception pertaining to the failure of the query will be thrown by the first access
   * to the {@link ResultSet}.
   *
   * <p>Note that for queries that doesn't return a result (INSERT, UPDATE and DELETE), you will
   * need to access the ResultSet (i.e. call any of its method) to make sure the query was
   * successful.
   *
   * @param query the CQL query to execute (that can be either a {@code Statement} or a {@code
   *     BoundStatement}). If it is a {@code BoundStatement}, all variables must have been bound
   *     (the statement must be ready).
   * @return a future on the result of the query.
   * @throws IllegalStateException if {@code query} is a {@code BoundStatement} but {@code
   *     !query.isReady()}.
   */
  public ResultSetFuture executeAsync(Query query) {

    if (query instanceof Statement) {
      return manager.executeQuery(
          new QueryMessage(
              ((Statement) query).getQueryString(),
              ConsistencyLevel.toCassandraCL(query.getConsistencyLevel())),
          query);
    } else {
      assert query instanceof BoundStatement : query;

      BoundStatement bs = (BoundStatement) query;
      if (!bs.isReady())
        throw new IllegalStateException(
            "Some bind variables haven't been bound in the provided statement");

      return manager.executeQuery(
          new ExecuteMessage(
              bs.statement.id,
              Arrays.asList(bs.values),
              ConsistencyLevel.toCassandraCL(query.getConsistencyLevel())),
          query);
    }
  }
    /** Loops collecting cql binded variable values from the queue and sending to Cassandra */
    public void run() {
      outer:
      while (run || !queue.isEmpty()) {
        List<ByteBuffer> bindVariables;
        try {
          bindVariables = queue.take();
        } catch (InterruptedException e) {
          // re-check loop condition after interrupt
          continue;
        }

        ListIterator<InetAddress> iter = endpoints.listIterator();
        while (true) {
          // send the mutation to the last-used endpoint.  first time through, this will NPE
          // harmlessly.
          try {
            int i = 0;
            PreparedStatement statement = preparedStatement(client);
            while (bindVariables != null) {
              BoundStatement boundStatement = new BoundStatement(statement);
              for (int columnPosition = 0;
                  columnPosition < bindVariables.size();
                  columnPosition++) {
                boundStatement.setBytesUnsafe(columnPosition, bindVariables.get(columnPosition));
              }
              client.execute(boundStatement);
              i++;

              if (i >= batchThreshold) break;
              bindVariables = queue.poll();
            }
            break;
          } catch (Exception e) {
            closeInternal();
            if (!iter.hasNext()) {
              lastException = new IOException(e);
              break outer;
            }
          }

          // attempt to connect to a different endpoint
          try {
            InetAddress address = iter.next();
            String host = address.getHostName();
            client = CqlConfigHelper.getOutputCluster(host, conf).connect();
          } catch (Exception e) {
            // If connection died due to Interrupt, just try connecting to the endpoint again.
            // There are too many ways for the Thread.interrupted() state to be cleared, so
            // we can't rely on that here. Until the java driver gives us a better way of knowing
            // that this exception came from an InterruptedException, this is the best solution.
            if (canRetryDriverConnection(e)) {
              iter.previous();
            }
            closeInternal();

            // Most exceptions mean something unexpected went wrong to that endpoint, so
            // we should try again to another.  Other exceptions (auth or invalid request) are
            // fatal.
            if ((e instanceof AuthenticationException || e instanceof InvalidQueryException)
                || !iter.hasNext()) {
              lastException = new IOException(e);
              break outer;
            }
          }
        }
      }
      // close all our connections once we are done.
      closeInternal();
    }