private void refreshEndpointMap() {
   String keyspace = ConfigHelper.getOutputKeyspace(conf);
   try (Session session =
       CqlConfigHelper.getOutputCluster(ConfigHelper.getOutputInitialAddress(conf), conf)
           .connect(keyspace)) {
     rangeMap = new HashMap<>();
     metadata = session.getCluster().getMetadata();
     Set<TokenRange> ranges = metadata.getTokenRanges();
     for (TokenRange range : ranges) {
       rangeMap.put(range, metadata.getReplicas(keyspace, range));
     }
   }
 }
    /** get prepared statement id from cache, otherwise prepare it from Cassandra server */
    private PreparedStatement preparedStatement(Session client) {
      PreparedStatement statement = preparedStatements.get(client);
      if (statement == null) {
        PreparedStatement result;
        try {
          result = client.prepare(cql);
        } catch (NoHostAvailableException e) {
          throw new RuntimeException("failed to prepare cql query " + cql, e);
        }

        PreparedStatement previousId = preparedStatements.putIfAbsent(client, result);
        statement = previousId == null ? result : previousId;
      }
      return statement;
    }
  CqlRecordWriter(Configuration conf) {
    this.conf = conf;
    this.queueSize =
        conf.getInt(ColumnFamilyOutputFormat.QUEUE_SIZE, 32 * FBUtilities.getAvailableProcessors());
    batchThreshold = conf.getLong(ColumnFamilyOutputFormat.BATCH_THRESHOLD, 32);
    this.clients = new HashMap<>();

    try {
      String keyspace = ConfigHelper.getOutputKeyspace(conf);
      try (Session client =
          CqlConfigHelper.getOutputCluster(ConfigHelper.getOutputInitialAddress(conf), conf)
              .connect(keyspace)) {
        ringCache = new NativeRingCache(conf);
        if (client != null) {
          TableMetadata tableMetadata =
              client
                  .getCluster()
                  .getMetadata()
                  .getKeyspace(client.getLoggedKeyspace())
                  .getTable(ConfigHelper.getOutputColumnFamily(conf));
          clusterColumns = tableMetadata.getClusteringColumns();
          partitionKeyColumns = tableMetadata.getPartitionKey();

          String cqlQuery = CqlConfigHelper.getOutputCql(conf).trim();
          if (cqlQuery.toLowerCase().startsWith("insert"))
            throw new UnsupportedOperationException(
                "INSERT with CqlRecordWriter is not supported, please use UPDATE/DELETE statement");
          cql = appendKeyWhereClauses(cqlQuery);
        } else {
          throw new IllegalArgumentException("Invalid configuration specified " + conf);
        }
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  @Test
  public void compressionTest() throws Exception {

    // Same as executeTest, but with compression enabled

    cluster
        .getConfiguration()
        .getProtocolOptions()
        .setCompression(ProtocolOptions.Compression.SNAPPY);

    try {

      Session compressedSession = cluster.connect(TestUtils.SIMPLE_KEYSPACE);

      // Simple calls to all versions of the execute/executeAsync methods
      String key = "execute_compressed_test";
      ResultSet rs =
          compressedSession.execute(String.format(INSERT_FORMAT, TABLE, key, "foo", 42, 24.03f));
      assertTrue(rs.isExhausted());

      String SELECT_ALL = String.format(SELECT_ALL_FORMAT + " WHERE k = '%s'", TABLE, key);

      // execute
      checkExecuteResultSet(compressedSession.execute(SELECT_ALL), key);
      checkExecuteResultSet(
          compressedSession.execute(
              new SimpleStatement(SELECT_ALL).setConsistencyLevel(ConsistencyLevel.ONE)),
          key);

      // executeAsync
      checkExecuteResultSet(compressedSession.executeAsync(SELECT_ALL).getUninterruptibly(), key);
      checkExecuteResultSet(
          compressedSession
              .executeAsync(
                  new SimpleStatement(SELECT_ALL).setConsistencyLevel(ConsistencyLevel.ONE))
              .getUninterruptibly(),
          key);

    } finally {
      cluster
          .getConfiguration()
          .getProtocolOptions()
          .setCompression(ProtocolOptions.Compression.NONE);
    }
  }
 protected void closeInternal() {
   if (client != null) {
     client.close();
   }
 }
    /** 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();
    }